지대한
2 years ago
commit
e9e335d0d1
709 changed files with 97902 additions and 0 deletions
@ -0,0 +1,5 @@ |
|||||||
|
SKIP_PREFLIGHT_CHECK=true |
||||||
|
REACT_APP_BASENAME= "" |
||||||
|
REACT_APP_HOST = http://control-api.palnet.co.kr/ |
||||||
|
REACT_APP_WS_HOST = ws://control-websocket.palnet.co.kr/ws |
||||||
|
REACT_APP_IMAGE_HOST = https://palnet-file.s3.ap-northeast-2.amazonaws.com/ |
@ -0,0 +1,3 @@ |
|||||||
|
REACT_APP_HOST = http://localhost:8080/ |
||||||
|
REACT_APP_WS_HOST = ws://localhost:8081/ws |
||||||
|
REACT_APP_IMAGE_HOST = https://palnet-file.s3.ap-northeast-2.amazonaws.com/ |
@ -0,0 +1,3 @@ |
|||||||
|
REACT_APP_HOST = http://control-api.palntour.com/ |
||||||
|
REACT_APP_WS_HOST = ws://control-websocket.palntour.com/ws |
||||||
|
REACT_APP_IMAGE_HOST = https://palnet-file.s3.ap-northeast-2.amazonaws.com/ |
@ -0,0 +1,81 @@ |
|||||||
|
module.exports = { |
||||||
|
env: { |
||||||
|
node: true, |
||||||
|
es6: true, |
||||||
|
browser: true |
||||||
|
}, |
||||||
|
parser: '@typescript-eslint/parser',
|
||||||
|
parserOptions: { |
||||||
|
ecmaVersion: 2018, |
||||||
|
sourceType: 'module', |
||||||
|
ecmaFeatures: { |
||||||
|
jsx: true, |
||||||
|
modules: true, |
||||||
|
experimentalObjectRestSpread: true |
||||||
|
} |
||||||
|
}, |
||||||
|
rules: { |
||||||
|
// 'no-console': 'off',
|
||||||
|
// 'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off',
|
||||||
|
// // Best Practices
|
||||||
|
// eqeqeq: 'error',
|
||||||
|
// 'no-invalid-this': 'error',
|
||||||
|
// 'no-return-assign': 'error',
|
||||||
|
// 'no-unused-expressions': ['error', { allowTernary: true }],
|
||||||
|
// 'no-useless-concat': 'error',
|
||||||
|
// 'no-useless-return': 'error',
|
||||||
|
// // Variable
|
||||||
|
// // 'init-declarations': 'error',
|
||||||
|
// 'no-use-before-define': 'error',
|
||||||
|
// // Stylistic Issues
|
||||||
|
// 'array-bracket-newline': ['error', { multiline: true, minItems: null }],
|
||||||
|
// 'array-bracket-spacing': 'error',
|
||||||
|
// 'brace-style': ['error', '1tbs', { allowSingleLine: true }],
|
||||||
|
// 'block-spacing': 'error',
|
||||||
|
// 'comma-dangle': 'error',
|
||||||
|
// 'comma-spacing': 'error',
|
||||||
|
// 'comma-style': 'error',
|
||||||
|
// 'computed-property-spacing': 'error',
|
||||||
|
// 'func-call-spacing': 'error',
|
||||||
|
// 'implicit-arrow-linebreak': ['error', 'beside'],
|
||||||
|
// // indent: ['error', 4],
|
||||||
|
// 'keyword-spacing': 'error',
|
||||||
|
// 'multiline-ternary': ['error', 'never'],
|
||||||
|
// // 'no-lonely-if': 'error',
|
||||||
|
// 'no-mixed-operators': 'error',
|
||||||
|
// 'no-multiple-empty-lines': ['error', { max: 2, maxEOF: 1 }],
|
||||||
|
// 'no-tabs': 'error',
|
||||||
|
// 'no-unneeded-ternary': 'error',
|
||||||
|
// 'no-whitespace-before-property': 'error',
|
||||||
|
// 'nonblock-statement-body-position': 'error',
|
||||||
|
// 'object-property-newline': [
|
||||||
|
// 'error',
|
||||||
|
// { allowAllPropertiesOnSameLine: true }
|
||||||
|
// ],
|
||||||
|
// 'quote-props': ['error', 'as-needed'],
|
||||||
|
// // quotes: ['error', 'prefer-single'],
|
||||||
|
// semi: ['error', 'never'],
|
||||||
|
// 'semi-spacing': 'error',
|
||||||
|
// 'space-before-blocks': 'error',
|
||||||
|
// // 'space-before-function-paren': 'error',
|
||||||
|
// 'space-in-parens': 'error',
|
||||||
|
// 'space-infix-ops': 'error',
|
||||||
|
// 'space-unary-ops': 'error',
|
||||||
|
// // ES6
|
||||||
|
// 'arrow-spacing': 'error',
|
||||||
|
// 'no-confusing-arrow': 'error',
|
||||||
|
// 'no-duplicate-imports': 'error',
|
||||||
|
// 'no-var': 'error',
|
||||||
|
// 'object-shorthand': 'error',
|
||||||
|
// 'prefer-const': 'error',
|
||||||
|
// 'prefer-template': 'error'
|
||||||
|
} |
||||||
|
|
||||||
|
// rules: {
|
||||||
|
// 'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off',
|
||||||
|
// 'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off',
|
||||||
|
// semi: ['error', 'never'],
|
||||||
|
// 'max-len': 'off',
|
||||||
|
// camelcase: ['error', { properties: 'never', ignoreDestructuring: true, ignoreImports: true }]
|
||||||
|
// }
|
||||||
|
}; |
@ -0,0 +1,29 @@ |
|||||||
|
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. |
||||||
|
|
||||||
|
# dependencies |
||||||
|
/node_modules |
||||||
|
/.pnp |
||||||
|
.pnp.js |
||||||
|
|
||||||
|
# testing |
||||||
|
/coverage |
||||||
|
|
||||||
|
# production |
||||||
|
/build |
||||||
|
|
||||||
|
# misc |
||||||
|
.DS_Store |
||||||
|
.env.local |
||||||
|
.env.development.local |
||||||
|
.env.test.local |
||||||
|
.env.production.local |
||||||
|
|
||||||
|
npm-debug.log* |
||||||
|
yarn-debug.log* |
||||||
|
yarn-error.log* |
||||||
|
|
||||||
|
.docz |
||||||
|
.eslintcache |
||||||
|
.vscode |
||||||
|
|
||||||
|
/react-shell-scripts |
@ -0,0 +1,11 @@ |
|||||||
|
module.exports = { |
||||||
|
singleQuote: true, //인용부호 작은 따옴표 사용
|
||||||
|
semi: true, //모든 문법 끝에 세미콜론 추가
|
||||||
|
useTabs: false, |
||||||
|
tabWidth: 2, //탭 공백 넓이
|
||||||
|
trailingComma: 'none', //후행 쉼표 제거
|
||||||
|
printWidth: 80, //줄바꿈 넓이
|
||||||
|
bracketSpacing: true, // 브라켓 간격
|
||||||
|
arrowParens: 'avoid', //arrow function 매개변수 하나일때 괄호 제거
|
||||||
|
jsxSingleQuote: true //jsx 인용부호 작은 따옴표 사용
|
||||||
|
}; |
Binary file not shown.
@ -0,0 +1,38 @@ |
|||||||
|
const SassRuleRewire = require('react-app-rewire-sass-rule') |
||||||
|
const path = require('path') |
||||||
|
const rewireAliases = require('react-app-rewire-aliases') |
||||||
|
|
||||||
|
module.exports = function override(config, env) { |
||||||
|
require('react-app-rewire-postcss')(config, { |
||||||
|
plugins: loader => [require('postcss-rtl')()] |
||||||
|
}) |
||||||
|
|
||||||
|
config = rewireAliases.aliasesOptions({ |
||||||
|
'@src': path.resolve(__dirname, 'src'), |
||||||
|
'@assets': path.resolve(__dirname, 'src/@core/assets'), |
||||||
|
'@components': path.resolve(__dirname, 'src/@core/components'), |
||||||
|
'@layouts': path.resolve(__dirname, 'src/@core/layouts'), |
||||||
|
'@store': path.resolve(__dirname, 'src/redux'), |
||||||
|
'@styles': path.resolve(__dirname, 'src/@core/scss'), |
||||||
|
'@configs': path.resolve(__dirname, 'src/configs'), |
||||||
|
'@utils': path.resolve(__dirname, 'src/utility/Utils'), |
||||||
|
'@hooks': path.resolve(__dirname, 'src/utility/hooks') |
||||||
|
})(config, env) |
||||||
|
|
||||||
|
config = new SassRuleRewire() |
||||||
|
.withRuleOptions({ |
||||||
|
test: /\.s[ac]ss$/i, |
||||||
|
use: [ |
||||||
|
{ |
||||||
|
loader: 'sass-loader', |
||||||
|
options: { |
||||||
|
sassOptions: { |
||||||
|
includePaths: ['node_modules', 'src/assets'] |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
] |
||||||
|
}) |
||||||
|
.rewire(config, env) |
||||||
|
return config |
||||||
|
} |
@ -0,0 +1,151 @@ |
|||||||
|
{ |
||||||
|
"name": "control-web", |
||||||
|
"version": "1.0.0", |
||||||
|
"private": true, |
||||||
|
"dependencies": { |
||||||
|
"@casl/ability": "5.2.2", |
||||||
|
"@casl/react": "2.1.1", |
||||||
|
"@fullcalendar/core": "5.7.2", |
||||||
|
"@fullcalendar/daygrid": "5.7.2", |
||||||
|
"@fullcalendar/interaction": "5.7.2", |
||||||
|
"@fullcalendar/list": "5.7.2", |
||||||
|
"@fullcalendar/react": "5.7.0", |
||||||
|
"@fullcalendar/timegrid": "5.7.2", |
||||||
|
"@fullcalendar/timeline": "5.7.2", |
||||||
|
"@hookform/resolvers": "1.3.4", |
||||||
|
"@stomp/stompjs": "^6.1.0", |
||||||
|
"@types/googlemaps": "^3.43.3", |
||||||
|
"@types/history": "^4.7.8", |
||||||
|
"@types/jest": "^26.0.23", |
||||||
|
"@types/node": "^15.12.2", |
||||||
|
"@types/react": "^17.0.11", |
||||||
|
"@types/react-dom": "^17.0.7", |
||||||
|
"@types/react-redux": "^7.1.16", |
||||||
|
"@types/redux-debounced": "^0.2.19", |
||||||
|
"@types/sockjs-client": "^1.5.0", |
||||||
|
"@types/stompjs": "^2.3.4", |
||||||
|
"@uppy/react": "1.10.8", |
||||||
|
"animate.css": "4.1.1", |
||||||
|
"apexcharts": "3.23.0", |
||||||
|
"availity-reactstrap-validation-safe": "2.6.1", |
||||||
|
"axios": "0.21.1", |
||||||
|
"axios-mock-adapter": "1.19.0", |
||||||
|
"babel-plugin-react-intl": "5.1.18", |
||||||
|
"bootstrap": "4.5.2", |
||||||
|
"bs-stepper": "1.7.0", |
||||||
|
"chart.js": "^2.9.4", |
||||||
|
"chroma-js": "2.1.0", |
||||||
|
"classnames": "2.2.6", |
||||||
|
"cleave.js": "1.6.0", |
||||||
|
"connected-react-router": "^6.9.1", |
||||||
|
"draft-js": "0.11.7", |
||||||
|
"draftjs-to-html": "0.9.1", |
||||||
|
"eslint-config-airbnb-base": "^14.2.1", |
||||||
|
"file-saver": "2.0.2", |
||||||
|
"flatpickr": "4.6.3", |
||||||
|
"history": "5.0.0", |
||||||
|
"html-to-draftjs": "1.5.0", |
||||||
|
"http-proxy-middleware": "^2.0.1", |
||||||
|
"intl-messageformat": "7.8.4", |
||||||
|
"jquery": "3.5.1", |
||||||
|
"js-cookie": "^3.0.0", |
||||||
|
"jsonwebtoken": "8.5.1", |
||||||
|
"jwt-decode": "^3.1.2", |
||||||
|
"leaflet": "1.6.0", |
||||||
|
"moment": "2.29.1", |
||||||
|
"nouislider": "14.6.2", |
||||||
|
"nouislider-react": "3.3.8", |
||||||
|
"postcss-rtl": "1.5.0", |
||||||
|
"prismjs": "1.19.0", |
||||||
|
"prop-types": "15.7.2", |
||||||
|
"react": "17.0.1", |
||||||
|
"react-apexcharts": "1.3.6", |
||||||
|
"react-chartjs-2": "^2.9.0", |
||||||
|
"react-contexify": "5.0.0", |
||||||
|
"react-copy-to-clipboard": "5.0.2", |
||||||
|
"react-country-flag": "2.0.1", |
||||||
|
"react-csv": "^2.0.3", |
||||||
|
"react-data-table-component": "6.11.2", |
||||||
|
"react-datepicker": "^4.2.1", |
||||||
|
"react-dom": "17.0.1", |
||||||
|
"react-draft-wysiwyg": "1.14.5", |
||||||
|
"react-export-excel": "^0.5.3", |
||||||
|
"react-feather": "~2.0.3", |
||||||
|
"react-flatpickr": "3.9.1", |
||||||
|
"react-google-maps": "^9.4.5", |
||||||
|
"react-hook-form": "6.15.1", |
||||||
|
"react-icons": "^4.2.0", |
||||||
|
"react-indiana-drag-scroll": "^2.0.1", |
||||||
|
"react-intl": "3.11.0", |
||||||
|
"react-leaflet": "3.1.0", |
||||||
|
"react-paginate": "7.0.0", |
||||||
|
"react-perfect-scrollbar": "1.5.5", |
||||||
|
"react-player": "2.6.2", |
||||||
|
"react-rating": "2.0.5", |
||||||
|
"react-redux": "7.2.2", |
||||||
|
"react-router-dom": "5.2.0", |
||||||
|
"react-scripts": "4.0.2", |
||||||
|
"react-scroll-up": "1.3.7", |
||||||
|
"react-select": "4.0.2", |
||||||
|
"react-shepherd": "3.3.0", |
||||||
|
"react-slidedown": "2.4.5", |
||||||
|
"react-sortablejs": "6.0.0", |
||||||
|
"react-toastify": "7.0.3", |
||||||
|
"reactstrap": "8.6.0", |
||||||
|
"recharts": "2.0.4", |
||||||
|
"redux": "4.0.5", |
||||||
|
"redux-debounced": "0.5.0", |
||||||
|
"redux-saga": "^1.1.3", |
||||||
|
"redux-thunk": "2.3.0", |
||||||
|
"sass": "1.26.8", |
||||||
|
"screenfull": "5.0.2", |
||||||
|
"sortablejs": "1.12.0", |
||||||
|
"styled-components": "5.1.1", |
||||||
|
"sweetalert2": "10.14.0", |
||||||
|
"sweetalert2-react-content": "3.0.1", |
||||||
|
"swiper": "6.0.4", |
||||||
|
"typesafe-actions": "^5.1.0", |
||||||
|
"uppy": "1.21.2", |
||||||
|
"webpack": "4.43.0", |
||||||
|
"wnumb": "1.2.0", |
||||||
|
"xlsx": "0.16.2", |
||||||
|
"yarn": "1.21.1", |
||||||
|
"yup": "0.32.8" |
||||||
|
}, |
||||||
|
"scripts": { |
||||||
|
"start": "react-app-rewired start", |
||||||
|
"build": "react-app-rewired build", |
||||||
|
"test": "react-app-rewired test", |
||||||
|
"eject": "react-app-rewired eject" |
||||||
|
}, |
||||||
|
"eslintConfig": { |
||||||
|
"extends": "react-app" |
||||||
|
}, |
||||||
|
"devDependencies": { |
||||||
|
"@types/sortablejs": "^1.10.6", |
||||||
|
"@typescript-eslint/eslint-plugin": "^4.28.1", |
||||||
|
"@typescript-eslint/parser": "^4.28.1", |
||||||
|
"eslint": "^7.29.0", |
||||||
|
"eslint-config-airbnb": "^18.2.1", |
||||||
|
"eslint-config-prettier": "^8.3.0", |
||||||
|
"eslint-plugin-import": "^2.23.4", |
||||||
|
"eslint-plugin-jsx-a11y": "^6.4.1", |
||||||
|
"eslint-plugin-prettier": "^3.4.0", |
||||||
|
"eslint-plugin-react": "^7.24.0", |
||||||
|
"eslint-plugin-react-hooks": "^1.7.0", |
||||||
|
"node-sass": "^4.13.1", |
||||||
|
"prettier": "^2.3.1", |
||||||
|
"react-app-rewire-aliases": "^0.2.0", |
||||||
|
"react-app-rewire-postcss": "^3.0.2", |
||||||
|
"react-app-rewire-sass-rule": "^2.1.1", |
||||||
|
"react-app-rewired": "^2.1.6", |
||||||
|
"sass-loader": "^8.0.2", |
||||||
|
"typescript": "^4.3.5" |
||||||
|
}, |
||||||
|
"browserslist": [ |
||||||
|
">0.2%", |
||||||
|
"not dead", |
||||||
|
"not op_mini all" |
||||||
|
], |
||||||
|
"homepage": "" |
||||||
|
} |
After Width: | Height: | Size: 4.2 KiB |
@ -0,0 +1,53 @@ |
|||||||
|
<!DOCTYPE html> |
||||||
|
<html lang="en" dir="ltr"> |
||||||
|
<head> |
||||||
|
<meta charset="utf-8" /> |
||||||
|
<!-- <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico" /> --> |
||||||
|
<meta |
||||||
|
name="viewport" |
||||||
|
content="width=device-width,initial-scale=1.0,maximum-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" /> |
||||||
|
<script |
||||||
|
type="text/javascript" |
||||||
|
src="https://openapi.map.naver.com/openapi/v3/maps.js?ncpClientId=5md90yszqj&submodules=geocoder"" |
||||||
|
></script> |
||||||
|
<!-- |
||||||
|
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`. |
||||||
|
--> |
||||||
|
<link |
||||||
|
rel="stylesheet" |
||||||
|
href="https://fonts.googleapis.com/css2?family=Montserrat:ital,wght@0,300;0,400;0,500;0,600;1,400;1,500;1,600" |
||||||
|
/> |
||||||
|
<link |
||||||
|
rel="stylesheet" |
||||||
|
href="https://unpkg.com/leaflet@1.5.1/dist/leaflet.css" |
||||||
|
crossorigin="" |
||||||
|
/> |
||||||
|
<title>Dron Control System</title> |
||||||
|
</head> |
||||||
|
<body> |
||||||
|
<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> |
@ -0,0 +1,15 @@ |
|||||||
|
{ |
||||||
|
"short_name": "React App", |
||||||
|
"name": "Create React App Sample", |
||||||
|
"icons": [ |
||||||
|
{ |
||||||
|
"src": "favicon.ico", |
||||||
|
"sizes": "64x64 32x32 24x24 16x16", |
||||||
|
"type": "image/x-icon" |
||||||
|
} |
||||||
|
], |
||||||
|
"start_url": ".", |
||||||
|
"display": "standalone", |
||||||
|
"theme_color": "#000000", |
||||||
|
"background_color": "#ffffff" |
||||||
|
} |
@ -0,0 +1,181 @@ |
|||||||
|
{ |
||||||
|
"Dashboards": "Instrumententafel", |
||||||
|
"Analytics": "Analytics", |
||||||
|
"eCommerce": "eCommerce", |
||||||
|
"Apps": "Apps", |
||||||
|
"Email": "Email", |
||||||
|
"Chat": "Plaudern", |
||||||
|
"Todo": "Machen", |
||||||
|
"Calendar": "Kalandar", |
||||||
|
"Ecommerce": "E-Commerce", |
||||||
|
"Shop": "Geschäft", |
||||||
|
"Wish List": "Wunschzettel", |
||||||
|
"Details": "Einzelheiten", |
||||||
|
"Checkout": "Auschecken", |
||||||
|
"User": "Benutzerin", |
||||||
|
"List": "Liste", |
||||||
|
"View": "Aussicht", |
||||||
|
"Edit": "Bearbeiten", |
||||||
|
"Starter Kit": "Starter Kit", |
||||||
|
"1 Column": "1 Spalte", |
||||||
|
"2 Columns": "2 Spalten", |
||||||
|
"Fixed Navbar": "Feste Navigationsleiste", |
||||||
|
"Floating Navbar": "Schwimmende Navigationsleiste", |
||||||
|
"Fixed Layout": "Festes Layout", |
||||||
|
"Static Layout": "Statisches Layout", |
||||||
|
"Dark Layout": "Dunkles Layout", |
||||||
|
"Light Layout": "Helles Layout", |
||||||
|
"Content": "Inhalt", |
||||||
|
"Grid": "Gitter", |
||||||
|
"Typography": "Typografie", |
||||||
|
"Text Utilities": "Textdienstprogramme", |
||||||
|
"Syntax Highlighter": "Syntax Textmarker", |
||||||
|
"Helper Classes": "Hilfsklassen", |
||||||
|
"Colors": "Farben", |
||||||
|
"Icons": "Icons", |
||||||
|
"Feather": "Feder", |
||||||
|
"UI Elements": "UI-Elemente", |
||||||
|
"Card": "Karte", |
||||||
|
"Basic": "Basic", |
||||||
|
"Advance": "Voraus", |
||||||
|
"Statistics": "Statistiken", |
||||||
|
"Actions": "Kartenaktionen", |
||||||
|
"Table": "Tabelle", |
||||||
|
"Reactstrap Tables": "Reactstrap Tabelles", |
||||||
|
"React Tables": "React Tabelles", |
||||||
|
"DataTable": "Datentabelle", |
||||||
|
"Advanced": "Fortgeschrittene", |
||||||
|
"Mail Template": "Mail-Vorlage", |
||||||
|
"Page Layouts": "Seitenlayouts", |
||||||
|
"Collapsed Menu": "Reduziertes Menü", |
||||||
|
"Layout Boxed": "Layout Boxed", |
||||||
|
"Without Menu": "Ohne Menü", |
||||||
|
"Layout Empty": "Layout leer", |
||||||
|
"Layout Blank": "Layout leer", |
||||||
|
"Components": "Komponenten", |
||||||
|
"Alerts": "Warnungen", |
||||||
|
"Buttons": "Tasten", |
||||||
|
"Breadcrumbs": "Semmelbrösel", |
||||||
|
"Carousel": "Karussell", |
||||||
|
"Collapse": "Zusammenbruch", |
||||||
|
"Dropdowns": "Dropdowns", |
||||||
|
"List Group": "Listengruppe", |
||||||
|
"Modals": "Modals", |
||||||
|
"Pagination": "Seitennummerierung", |
||||||
|
"Navs Component": "Navs-Komponente", |
||||||
|
"Navbar": "Navbar", |
||||||
|
"Tabs Component": "Registerkarten-Komponente", |
||||||
|
"Pills Component": "Pillenkomponente", |
||||||
|
"Tooltips": "Tooltips", |
||||||
|
"Popovers": "Popovers", |
||||||
|
"Badges": "Abzeichen", |
||||||
|
"Pill Badges": "Pillenabzeichen", |
||||||
|
"Progress": "Fortschritt", |
||||||
|
"Media Objects": "Medienobjekte", |
||||||
|
"Spinner": "Spinner", |
||||||
|
"Toasts": "Toast", |
||||||
|
"Timeline": "Zeitleiste", |
||||||
|
"Extra Components": "Zusätzliche Komponenten", |
||||||
|
"Avatar": "Benutzerbild", |
||||||
|
"Chips": "Chips", |
||||||
|
"Divider": "Teiler", |
||||||
|
"Wizard": "Magier", |
||||||
|
"Forms & Tables": "Formulare und Tabellen", |
||||||
|
"Form Elements": "Formularelemente", |
||||||
|
"Select": "Wählen", |
||||||
|
"Switch": "Schalter", |
||||||
|
"Checkbox": "Kontrollkästchen", |
||||||
|
"Radio": "Radio", |
||||||
|
"Input": "Eingang", |
||||||
|
"Input Groups": "Eingabegruppen", |
||||||
|
"Number Input": "Zahleneingabe", |
||||||
|
"Textarea": "Textarea", |
||||||
|
"Date & Time Picker": "Datums- und Uhrzeitauswahl", |
||||||
|
"Input Mask": "Eingabemaske", |
||||||
|
"Form Layout": "Formularlayout", |
||||||
|
"Form Wizard": "Formzauberer", |
||||||
|
"Form Validation": "Formularvalidierung", |
||||||
|
"Formik": "Formik", |
||||||
|
"Pages": "Seiten", |
||||||
|
"Authentication": "Authentifizierung", |
||||||
|
"Login v1": "Einloggen v1", |
||||||
|
"Login v2": "Einloggen v2", |
||||||
|
"Register v1": "Registrieren v1", |
||||||
|
"Register v2": "Registrieren v2", |
||||||
|
"Forgot Password v1": "Passwort vergessen v1", |
||||||
|
"Forgot Password v2": "Passwort vergessen v2", |
||||||
|
"Reset Password v1": "Passwort zurücksetzen v1", |
||||||
|
"Reset Password v2": "Passwort zurücksetzen v2", |
||||||
|
"Coming Soon": "Demnächst", |
||||||
|
"Error": "Error", |
||||||
|
"Not Authorized": "Nicht berechtigt", |
||||||
|
"Maintenance": "Instandhaltung", |
||||||
|
"Profile": "Profil", |
||||||
|
"Account Settings": "Account Einstellungen", |
||||||
|
"Tree": "Baum", |
||||||
|
"Miscellaneous": "Sonstiges", |
||||||
|
"FAQ": "FAQ", |
||||||
|
"Knowledge Base": "Wissensbasis", |
||||||
|
"Search": "Suche", |
||||||
|
"Invoice": "Rechnung", |
||||||
|
"Charts & Maps": "Karten & Pläne", |
||||||
|
"Charts": "Diagramme", |
||||||
|
"Apex": "Apex", |
||||||
|
"ChartJS": "ChartJS", |
||||||
|
"Recharts": "Recharts", |
||||||
|
"Leaflet Maps": "Leaflet Maps", |
||||||
|
"Extensions": "Erweiterungen", |
||||||
|
"Sweet Alert": "Süßer Alarm", |
||||||
|
"Toastr": "Toastr", |
||||||
|
"Sliders": "Schieberegler", |
||||||
|
"File Uploader": "Datei-Uploader", |
||||||
|
"Editor": "Editor", |
||||||
|
"Drag & Drop": "Ziehen und loslassen", |
||||||
|
"Tour": "Tour", |
||||||
|
"Auto Complete": "Automatisch vervollständigen", |
||||||
|
"Clipboard": "Zwischenablage", |
||||||
|
"React Player": "Reagieren Player", |
||||||
|
"Context Menu": "Kontextmenü", |
||||||
|
"Swiper": "Swiper", |
||||||
|
"I18n": "I18n", |
||||||
|
"React Paginate": "Paginieren reagieren", |
||||||
|
"Export": "Export", |
||||||
|
"Import": "Importieren", |
||||||
|
"Export Selected": "Ausgewählte exportieren", |
||||||
|
"Access Control": "Zugangskontrolle", |
||||||
|
"Others": "Andere", |
||||||
|
"Menu Levels": "Menüebenen", |
||||||
|
"Second Level": "zweites Level", |
||||||
|
"Second Level 2.1": "zweites Level 2.1", |
||||||
|
"Second Level 2.2": "zweites Level 2.2", |
||||||
|
"Third Level": "Drittes Level", |
||||||
|
"Third Level 3.1": "Drittes Level 3.1", |
||||||
|
"Third Level 3.2": "Drittes Level 2.2", |
||||||
|
"Disabled Menu": "Deaktiviertes Menü", |
||||||
|
"Documentation": "Dokumentation", |
||||||
|
"Raise Support": "Unterstützung erhöhen", |
||||||
|
"Change Log": "Änderungsprotokoll", |
||||||
|
"text": "Kuchen Sesam Snaps Cupcake Lebkuchen dänisch Ich liebe Lebkuchen. Apfelkuchen Jujubes Chupa Chups Muffin Halvah Lutscher. Schokoladenkuchen-Haferkuchen-Tiramisumarzipanzuckerpflaume. Donut süße Torte Haferkuchen Dragée Obstkuchen Zuckerwatte Zitronentropfen.", |
||||||
|
"Pricing": "Preisgestaltung", |
||||||
|
"Blog": "Blog", |
||||||
|
"Detail": "Einzelheiten", |
||||||
|
"Form Repeater": "Form Repeater", |
||||||
|
"Preview": "Vorschau", |
||||||
|
"Add": "Hinzufügen", |
||||||
|
"Ratings": "Bewertungen", |
||||||
|
"show": "show", |
||||||
|
"entries": "einträge", |
||||||
|
"search": "suche", |
||||||
|
"Prev": "Zurück", |
||||||
|
"Next": "Nächster", |
||||||
|
"BlockUI": "BlockUI", |
||||||
|
"Reactstrap": "Reactstrap", |
||||||
|
"Welcome": "Herzlich willkommen", |
||||||
|
"Reset Password": "Passwort zurücksetzen", |
||||||
|
"Verify Email": "E-Mail bestätigen", |
||||||
|
"Deactivate Account": "Benutzerkonto deaktivieren", |
||||||
|
"Promotional": "Werbung", |
||||||
|
"Apps & Pages": "Apps & Seiten", |
||||||
|
"User Interface": "Benutzeroberfläche", |
||||||
|
"Misc": "Sonstiges" |
||||||
|
} |
@ -0,0 +1,179 @@ |
|||||||
|
{ |
||||||
|
"Dashboards": "Dashboards", |
||||||
|
"Analytics": "Analytics", |
||||||
|
"Apps": "Apps", |
||||||
|
"eCommerce": "eCommerce", |
||||||
|
"Email": "Email", |
||||||
|
"Chat": "Chat", |
||||||
|
"Todo": "Todo", |
||||||
|
"Calendar": "Calendar", |
||||||
|
"Ecommerce": "Ecommerce", |
||||||
|
"Shop": "Shop", |
||||||
|
"Wish List": "Wish List", |
||||||
|
"Details": "Details", |
||||||
|
"Checkout": "Checkout", |
||||||
|
"User": "User", |
||||||
|
"List": "List", |
||||||
|
"View": "View", |
||||||
|
"Edit": "Edit", |
||||||
|
"Starter Kit": "Starter Kit", |
||||||
|
"1 Column": "1 Column", |
||||||
|
"2 Columns": "2 Columns", |
||||||
|
"Fixed Navbar": "Fixed Navbar", |
||||||
|
"Floating Navbar": "Floating Navbar", |
||||||
|
"Fixed Layout": "Fixed Layout", |
||||||
|
"Static Layout": "Static Layout", |
||||||
|
"Dark Layout": "Dark Layout", |
||||||
|
"Light Layout": "Light Layout", |
||||||
|
"UI Elements": "UI Elements", |
||||||
|
"Content": "Content", |
||||||
|
"Grid": "Grid", |
||||||
|
"Typography": "Typography", |
||||||
|
"Text Utilities": "Text Utilities", |
||||||
|
"Syntax Highlighter": "Syntax Highlighter", |
||||||
|
"Colors": "Colors", |
||||||
|
"Icons": "Icons", |
||||||
|
"Feather": "Feather", |
||||||
|
"Card": "Card", |
||||||
|
"Basic": "Basic", |
||||||
|
"Advance": "Advance", |
||||||
|
"Statistics": "Statistics", |
||||||
|
"Actions": "Actions", |
||||||
|
"Table": "Table", |
||||||
|
"Reactstrap Tables": "Reactstrap Tables", |
||||||
|
"React Tables": "React Tables", |
||||||
|
"DataTable": "DataTable", |
||||||
|
"Advanced": "Advanced", |
||||||
|
"Mail Template": "Mail Template", |
||||||
|
"Page Layouts": "Page Layouts", |
||||||
|
"Collapsed Menu": "Collapsed Menu", |
||||||
|
"Layout Boxed": "Layout Boxed", |
||||||
|
"Without Menu": "Without Menu", |
||||||
|
"Layout Empty": "Layout Empty", |
||||||
|
"Layout Blank": "Layout Blank", |
||||||
|
"Components": "Components", |
||||||
|
"Alerts": "Alerts", |
||||||
|
"Buttons": "Buttons", |
||||||
|
"Breadcrumbs": "Breadcrumbs", |
||||||
|
"Carousel": "Carousel", |
||||||
|
"Collapse": "Collapse", |
||||||
|
"Dropdowns": "Dropdowns", |
||||||
|
"List Group": "List Group", |
||||||
|
"Modals": "Modals", |
||||||
|
"Pagination": "Pagination", |
||||||
|
"Navs Component": "Navs Component", |
||||||
|
"Navbar": "Navbar", |
||||||
|
"Tabs Component": "Tabs Component", |
||||||
|
"Pills Component": "Pills Component", |
||||||
|
"Tooltips": "Tooltips", |
||||||
|
"Popovers": "Popovers", |
||||||
|
"Badges": "Badges", |
||||||
|
"Pill Badges": "Pill Badges", |
||||||
|
"Progress": "Progress", |
||||||
|
"Media Objects": "Media Objects", |
||||||
|
"Spinner": "Spinner", |
||||||
|
"Toasts": "Toasts", |
||||||
|
"Timeline": "Timeline", |
||||||
|
"Extra Components": "Extra Components", |
||||||
|
"Avatar": "Avatar", |
||||||
|
"Chips": "Chips", |
||||||
|
"Divider": "Divider", |
||||||
|
"Wizard": "Wizard", |
||||||
|
"Forms & Tables": "Forms & Tables", |
||||||
|
"Form Elements": "Form Elements", |
||||||
|
"Select": "Select", |
||||||
|
"Switch": "Switch", |
||||||
|
"Checkbox": "Checkbox", |
||||||
|
"Radio": "Radio", |
||||||
|
"Input": "Input", |
||||||
|
"Input Groups": "Input Groups", |
||||||
|
"Number Input": "Number Input", |
||||||
|
"Textarea": "Textarea", |
||||||
|
"Date & Time Picker": "Date & Time Picker", |
||||||
|
"Input Mask": "Input Mask", |
||||||
|
"Form Layout": "Form Layout", |
||||||
|
"Form Wizard": "Form Wizard", |
||||||
|
"Formik": "Formik", |
||||||
|
"Form Validation": "Form Validation", |
||||||
|
"Pages": "Pages", |
||||||
|
"Authentication": "Authentication", |
||||||
|
"Login v1": "Login v1", |
||||||
|
"Login v2": "Login v2", |
||||||
|
"Register v1": "Register v1", |
||||||
|
"Register v2": "Register v2", |
||||||
|
"Forgot Password v1": "Forgot Password v1", |
||||||
|
"Forgot Password v2": "Forgot Password v2", |
||||||
|
"Reset Password v1": "Reset Password v1", |
||||||
|
"Reset Password v2": "Reset Password v2", |
||||||
|
"Miscellaneous": "Miscellaneous", |
||||||
|
"Coming Soon": "Coming Soon", |
||||||
|
"Error": "Error", |
||||||
|
"Not Authorized": "Not Authorized", |
||||||
|
"Maintenance": "Maintenance", |
||||||
|
"Extensions": "Extensions", |
||||||
|
"Profile": "Profile", |
||||||
|
"Account Settings": "Account Settings", |
||||||
|
"FAQ": "FAQ", |
||||||
|
"Knowledge Base": "Knowledge Base", |
||||||
|
"Search": "Search", |
||||||
|
"Invoice": "Invoice", |
||||||
|
"Charts & Maps": "Charts & Maps", |
||||||
|
"Charts": "Charts", |
||||||
|
"Apex": "Apex", |
||||||
|
"ChartJS": "ChartJS", |
||||||
|
"Recharts": "Recharts", |
||||||
|
"Leaflet Maps": "Leaflet Maps", |
||||||
|
"Sweet Alert": "Sweet Alert", |
||||||
|
"Toastr": "Toastr", |
||||||
|
"Sliders": "Sliders", |
||||||
|
"File Uploader": "File Uploader", |
||||||
|
"Editor": "Editor", |
||||||
|
"Drag & Drop": "Drag & Drop", |
||||||
|
"Tour": "Tour", |
||||||
|
"Auto Complete": "Auto Complete", |
||||||
|
"Clipboard": "Clipboard", |
||||||
|
"React Player": "React Player", |
||||||
|
"Swiper": "Swiper", |
||||||
|
"Context Menu": "Context Menu", |
||||||
|
"Tree": "Tree", |
||||||
|
"I18n": "I18n", |
||||||
|
"React Paginate": "React Paginate", |
||||||
|
"Export": "Export", |
||||||
|
"Import": "Import", |
||||||
|
"Export Selected": "Export Selected", |
||||||
|
"Access Control": "Access Control", |
||||||
|
"Others": "Others", |
||||||
|
"Menu Levels": "Menu Levels", |
||||||
|
"Second Level": "Second Level", |
||||||
|
"Second Level 2.1": "Second Level 2.1", |
||||||
|
"Second Level 2.2": "Second Level 2.2", |
||||||
|
"Third Level 3.1": "Third Level 3.1", |
||||||
|
"Third Level 3.2": "Third Level 3.2", |
||||||
|
"Disabled Menu": "Disabled Menu", |
||||||
|
"Documentation": "Documentation", |
||||||
|
"Raise Support": "Raise Support", |
||||||
|
"Change Log": "Change Log", |
||||||
|
"text": "Cake sesame snaps cupcake gingerbread danish I love gingerbread. Apple pie pie jujubes chupa chups muffin halvah lollipop. Chocolate cake oat cake tiramisu marzipan sugar plum. Donut sweet pie oat cake dragée fruitcake cotton candy lemon drops.", |
||||||
|
"Pricing": "Pricing", |
||||||
|
"Blog": "Blog", |
||||||
|
"Detail": "Detail", |
||||||
|
"Form Repeater": "Form Repeater", |
||||||
|
"Preview": "Preview", |
||||||
|
"Add": "Add", |
||||||
|
"Ratings": "Ratings", |
||||||
|
"show": "show", |
||||||
|
"entries": "entries", |
||||||
|
"search": "search", |
||||||
|
"Prev": "Prev", |
||||||
|
"Next": "Next", |
||||||
|
"BlockUI": "BlockUI", |
||||||
|
"Reactstrap": "Reactstrap", |
||||||
|
"Welcome": "Welcome", |
||||||
|
"Reset Password": "Reset Password", |
||||||
|
"Verify Email": "Verify Email", |
||||||
|
"Deactivate Account": "Deactivate Account", |
||||||
|
"Promotional": "Promotional", |
||||||
|
"Apps & Pages": "Apps & Pages", |
||||||
|
"User Interface": "User Interface", |
||||||
|
"Misc": "Misc" |
||||||
|
} |
@ -0,0 +1,180 @@ |
|||||||
|
{ |
||||||
|
"Dashboards": "Tableau de bord", |
||||||
|
"Analytics": "Analytique", |
||||||
|
"Apps": "applications", |
||||||
|
"eCommerce": "commerce électronique", |
||||||
|
"Email": "Email", |
||||||
|
"Chat": "Bavarder", |
||||||
|
"Todo": "Faire", |
||||||
|
"Calendar": "Calandre", |
||||||
|
"Ecommerce": "Commerce électronique", |
||||||
|
"Shop": "Boutique", |
||||||
|
"Wish List": "Liste de souhaits", |
||||||
|
"Details": "Détails", |
||||||
|
"User": "Utilisatrice", |
||||||
|
"List": "liste", |
||||||
|
"View": "Vue", |
||||||
|
"Edit": "modifier", |
||||||
|
"Checkout": "Check-out", |
||||||
|
"Starter Kit": "Kit de démarrage", |
||||||
|
"1 Column": "1 colonne", |
||||||
|
"2 Columns": "2 colonnes", |
||||||
|
"Fixed Navbar": "Barre de navigation fixe", |
||||||
|
"Floating Navbar": "Barre de navigation flottante", |
||||||
|
"Fixed Layout": "Mise en page fixe", |
||||||
|
"Static Layout": "Disposition statique", |
||||||
|
"Dark Layout": "Mise en page sombre", |
||||||
|
"Light Layout": "Mise en lumière", |
||||||
|
"UI Elements": "Éléments d'interface utilisateur", |
||||||
|
"Content": "Contenu", |
||||||
|
"Grid": "la grille", |
||||||
|
"Typography": "Typographie", |
||||||
|
"Text Utilities": "Utilitaires de texte", |
||||||
|
"Syntax Highlighter": "Surligneur de syntaxe", |
||||||
|
"Colors": "Couleurs", |
||||||
|
"Icons": "Les icônes", |
||||||
|
"Feather": "Plume", |
||||||
|
"Card": "Carte", |
||||||
|
"Basic": "De base", |
||||||
|
"Advance": "Avance", |
||||||
|
"Statistics": "Statistiques", |
||||||
|
"Actions": "Actions de carte", |
||||||
|
"Table": "Table", |
||||||
|
"Reactstrap Tables": "Tables de réactstrap", |
||||||
|
"React Tables": "Tables de réaction", |
||||||
|
"DataTable": "DataTable", |
||||||
|
"Advanced": "Avancé", |
||||||
|
"Mail Template": "Modèle de courrier", |
||||||
|
"Page Layouts": "Mises en page", |
||||||
|
"Collapsed Menu": "Menu réduit", |
||||||
|
"Layout Boxed": "Disposition encadrée", |
||||||
|
"Without Menu": "Sans menu", |
||||||
|
"Layout Empty": "Disposition vide", |
||||||
|
"Layout Blank": "Mise en page vierge", |
||||||
|
"Components": "Composants", |
||||||
|
"Alerts": "Les alertes", |
||||||
|
"Buttons": "Boutons", |
||||||
|
"Breadcrumbs": "Chapelure", |
||||||
|
"Carousel": "Carrousel", |
||||||
|
"Collapse": "Effondrer", |
||||||
|
"Dropdowns": "Des listes déroulantes", |
||||||
|
"List Group": "Groupe de liste", |
||||||
|
"Modals": "Modaux", |
||||||
|
"Pagination": "Pagination", |
||||||
|
"Navs Component": "Composante navs", |
||||||
|
"Navbar": "Barre de navigation", |
||||||
|
"Tabs Component": "Composant Onglets", |
||||||
|
"Pills Component": "Composant pilules", |
||||||
|
"Tooltips": "Info-bulles", |
||||||
|
"Popovers": "popovers", |
||||||
|
"Badges": "Insignes", |
||||||
|
"Pill Badges": "Insignes de pilule", |
||||||
|
"Progress": "Le progrès", |
||||||
|
"Media Objects": "Objets multimédia", |
||||||
|
"Spinner": "Fileur", |
||||||
|
"Toasts": "Toasts", |
||||||
|
"Timeline": "Chronologie", |
||||||
|
"Extra Components": "Composants Extra", |
||||||
|
"Avatar": "Avatar", |
||||||
|
"Chips": "chips", |
||||||
|
"Divider": "Diviseur", |
||||||
|
"Wizard": "sorcier", |
||||||
|
"Form Elements": "Éléments de formulaire", |
||||||
|
"Forms & Tables": "Formulaires et tableaux", |
||||||
|
"Select": "Sélectionner", |
||||||
|
"Switch": "Commutateur", |
||||||
|
"Checkbox": "Case à cocher", |
||||||
|
"Radio": "Radio", |
||||||
|
"Input": "Contribution", |
||||||
|
"Input Groups": "Groupes d'entrée", |
||||||
|
"Number Input": "Nombre d'entrée", |
||||||
|
"Textarea": "Textarea", |
||||||
|
"Date & Time Picker": "Sélecteur de date et heure", |
||||||
|
"Input Mask": "Masque de saisie", |
||||||
|
"Form Layout": "Disposition du formulaire", |
||||||
|
"Form Wizard": "Assistant de formulaire", |
||||||
|
"Form Validation": "Validation de formulaire", |
||||||
|
"Formik": "Formik", |
||||||
|
"Pages": "Des pages", |
||||||
|
"Authentication": "Authentification", |
||||||
|
"Login v1": "S'identifier v1", |
||||||
|
"Login v2": "S'identifier v2", |
||||||
|
"Register v1": "S'inscrire v1", |
||||||
|
"Register v2": "S'inscrire v2", |
||||||
|
"Forgot Password v1": "Mot de passe oublié v1", |
||||||
|
"Forgot Password v2": "Mot de passe oublié v2", |
||||||
|
"Reset Password v1": "réinitialiser le mot de passe v1", |
||||||
|
"Reset Password v2": "réinitialiser le mot de passe v2", |
||||||
|
"Coming Soon": "Arrive bientôt", |
||||||
|
"Error": "Erreur", |
||||||
|
"Not Authorized": "Pas autorisé", |
||||||
|
"Maintenance": "Entretien", |
||||||
|
"Profile": "Profil", |
||||||
|
"Account Settings": "Paramètres du compte", |
||||||
|
"FAQ": "FAQ", |
||||||
|
"Knowledge Base": "Base de connaissances", |
||||||
|
"Search": "Chercher", |
||||||
|
"Invoice": "Facture d'achat", |
||||||
|
"Charts & Maps": "Graphiques et cartes", |
||||||
|
"Charts": "Graphiques", |
||||||
|
"Apex": "Sommet", |
||||||
|
"ChartJS": "ChartJS", |
||||||
|
"Recharts": "Recharts", |
||||||
|
"Leaflet Maps": "Leaflet Maps", |
||||||
|
"Extensions": "Les extensions", |
||||||
|
"Sweet Alert": "Douce alerte", |
||||||
|
"Toastr": "Toastr", |
||||||
|
"Sliders": "Curseurs", |
||||||
|
"File Uploader": "Chargeur de fichiers", |
||||||
|
"Editor": "éditeur", |
||||||
|
"Swiper": "Swiper", |
||||||
|
"Tree": "Arbre", |
||||||
|
"Drag & Drop": "Drag & Drop", |
||||||
|
"Tour": "Tour", |
||||||
|
"Auto Complete": "+Terminé automatiquement", |
||||||
|
"Clipboard": "Presse-papiers", |
||||||
|
"React Player": "Réagir multimédia", |
||||||
|
"Context Menu": "Menu contextuel", |
||||||
|
"Miscellaneous": "Divers", |
||||||
|
"I18n": "I18n", |
||||||
|
"React Paginate": "Réagir Paginer", |
||||||
|
"Export": "Exportation", |
||||||
|
"Import": "Importation", |
||||||
|
"Export Selected": "Exporter la sélection", |
||||||
|
"Access Control": "Contrôle d'accès", |
||||||
|
"Others": "Autres", |
||||||
|
"Menu Levels": "Niveaux de menu", |
||||||
|
"Second Level": "Deuxième niveau", |
||||||
|
"Second Level 2.1": "Deuxième niveau 2.1", |
||||||
|
"Second Level 2.2": "Deuxième niveau 2.2", |
||||||
|
"Third Level": "Troisième niveau", |
||||||
|
"Third Level 3.1": "Troisième niveau 3.1", |
||||||
|
"Third Level 3.2": "Troisième niveau 3.2", |
||||||
|
"Disabled Menu": "Menu désactivé", |
||||||
|
"Documentation": "Documentation", |
||||||
|
"Raise Support": "Augmenter le soutien", |
||||||
|
"Change Log": "Changer le journal", |
||||||
|
"text": "Gâteau au sésame s'enclenche petit pain au pain d'épices danois J'adore le pain d'épices. Tarte aux pommes jujubes chupa chups muffin halvah lollipop. Gateau au chocolat gateau d 'avoine tiramisu prune sucre. Donut tarte sucrée gâteau à l'avoine dragée gouttes de fruits gâteau au citron en barbe à papa.", |
||||||
|
"Pricing": "Tarification", |
||||||
|
"Blog": "Blog", |
||||||
|
"Detail": "Détails", |
||||||
|
"Form Repeater": "Répétiteur de formulaire", |
||||||
|
"Preview": "Aperçu", |
||||||
|
"Add": "Ajouter", |
||||||
|
"Ratings": "Évaluations", |
||||||
|
"show": "spectacle", |
||||||
|
"entries": "entrées", |
||||||
|
"search": "chercher", |
||||||
|
"Prev": "Précédente", |
||||||
|
"Next": "Prochain", |
||||||
|
"BlockUI": "BlockUI", |
||||||
|
"Reactstrap": "Reactstrap", |
||||||
|
"Welcome": "Welcome", |
||||||
|
"Reset Password": "Réinitialiser le mot de passe", |
||||||
|
"Verify Email": "Vérifier l'e-mail", |
||||||
|
"Deactivate Account": "Désactiver le compte", |
||||||
|
"Promotional": "Promotionnel", |
||||||
|
"Apps & Pages": "Applications et pages", |
||||||
|
"User Interface": "Interface utilisateur", |
||||||
|
"Misc": "Divers" |
||||||
|
} |
@ -0,0 +1,181 @@ |
|||||||
|
{ |
||||||
|
"Dashboards": "painel de controle", |
||||||
|
"Analytics": "Analytics", |
||||||
|
"eCommerce": "comércio eletrônico", |
||||||
|
"Apps": "Apps", |
||||||
|
"Email": "O email", |
||||||
|
"Chat": "Bate-papo", |
||||||
|
"Todo": "Façam", |
||||||
|
"Calendar": "Calendário", |
||||||
|
"Ecommerce": "Comércio eletrônico", |
||||||
|
"Shop": "fazer compras", |
||||||
|
"Wish List": "Lista de Desejos", |
||||||
|
"Details": "Detalhes", |
||||||
|
"Checkout": "Confira", |
||||||
|
"User": "Do utilizador", |
||||||
|
"List": "Lista", |
||||||
|
"View": "Visão", |
||||||
|
"Edit": "Editar", |
||||||
|
"Starter Kit": "Kit iniciante", |
||||||
|
"1 Column": "1 coluna", |
||||||
|
"2 Columns": "2 colunas", |
||||||
|
"Fixed Navbar": "Navbar fixa", |
||||||
|
"Floating Navbar": "Navbar flutuante", |
||||||
|
"Fixed Layout": "Layout fixo", |
||||||
|
"Static Layout": "Layout estático", |
||||||
|
"Dark Layout": "Layout escuro", |
||||||
|
"Light Layout": "Layout de luz", |
||||||
|
"Content": "Conteúdo", |
||||||
|
"Grid": "Grade", |
||||||
|
"Typography": "Tipografia", |
||||||
|
"Text Utilities": "Utilitários de texto", |
||||||
|
"Syntax Highlighter": "Marcador de sintaxe", |
||||||
|
"Helper Classes": "Classes Auxiliares", |
||||||
|
"Colors": "Cores", |
||||||
|
"Icons": "Ícones", |
||||||
|
"Feather": "Pena", |
||||||
|
"UI Elements": "Elementos da interface do usuário", |
||||||
|
"Card": "Cartão", |
||||||
|
"Basic": "Basic", |
||||||
|
"Advance": "Avançar", |
||||||
|
"Statistics": "Estatisticas", |
||||||
|
"Actions": "Ações do Cartão", |
||||||
|
"Table": "Tabela", |
||||||
|
"Reactstrap Tables": "Mesa Reactstrap", |
||||||
|
"React Tables": "Mesa React", |
||||||
|
"DataTable": "Tabela de dados", |
||||||
|
"Advanced": "Avançado", |
||||||
|
"Mail Template": "Modelo de Correio", |
||||||
|
"Page Layouts": "Layouts de página", |
||||||
|
"Collapsed Menu": "Menu recolhido", |
||||||
|
"Layout Boxed": "Layout em caixa", |
||||||
|
"Without Menu": "Sem Menu", |
||||||
|
"Layout Empty": "Layout vazio", |
||||||
|
"Layout Blank": "Layout em branco", |
||||||
|
"Components": "Componentes", |
||||||
|
"Alerts": "Alertas", |
||||||
|
"Buttons": "Botões", |
||||||
|
"Breadcrumbs": "Pão ralado", |
||||||
|
"Carousel": "Carrossel", |
||||||
|
"Collapse": "Colapso", |
||||||
|
"Dropdowns": "Dropdowns", |
||||||
|
"List Group": "Grupo de listas", |
||||||
|
"Modals": "Modais", |
||||||
|
"Pagination": "Paginação", |
||||||
|
"Navs Component": "Componente Navs", |
||||||
|
"Navbar": "Navbar", |
||||||
|
"Tabs Component": "Componente de guias", |
||||||
|
"Pills Component": "Componente de comprimidos", |
||||||
|
"Tooltips": "Dicas de ferramentas", |
||||||
|
"Popovers": "Popovers", |
||||||
|
"Badges": "Distintivos", |
||||||
|
"Pill Badges": "Emblemas de pílula", |
||||||
|
"Progress": "Progresso", |
||||||
|
"Media Objects": "Objetos de Mídia", |
||||||
|
"Spinner": "Girador", |
||||||
|
"Toasts": "Torradas", |
||||||
|
"Timeline": "Linha do tempo", |
||||||
|
"Extra Components": "Componentes extras", |
||||||
|
"Avatar": "Avatar", |
||||||
|
"Chips": "Salgadinhos", |
||||||
|
"Divider": "Divisor", |
||||||
|
"Wizard": "Mago", |
||||||
|
"Form Elements": "Elementos do formulário", |
||||||
|
"Forms & Tables": "Formulários e tabelas", |
||||||
|
"Select": "Selecione", |
||||||
|
"Switch": "Interruptor", |
||||||
|
"Checkbox": "Caixa de seleção", |
||||||
|
"Radio": "Rádio", |
||||||
|
"Input": "Entrada", |
||||||
|
"Input Groups": "Grupos de entrada", |
||||||
|
"Number Input": "Entrada numérica", |
||||||
|
"Textarea": "Textarea", |
||||||
|
"Date & Time Picker": "Selecionador de data e hora", |
||||||
|
"Input Mask": "Máscara de entrada", |
||||||
|
"Form Layout": "Layout do formulário", |
||||||
|
"Form Wizard": "Assistente de Formulário", |
||||||
|
"Form Validation": "Validação de Formulário", |
||||||
|
"Formik": "Formik", |
||||||
|
"Pages": "Páginas", |
||||||
|
"Authentication": "Autenticação", |
||||||
|
"Login v1": "Conecte-se v1", |
||||||
|
"Login v2": "Conecte-se v2", |
||||||
|
"Register v1": "Registro v1", |
||||||
|
"Register v2": "Registro v2", |
||||||
|
"Forgot Password v1": "Esqueceu a senha v1", |
||||||
|
"Forgot Password v2": "Esqueceu a senha v2", |
||||||
|
"Reset Password v1": "Redefinir senha v1", |
||||||
|
"Reset Password v2": "Redefinir senha v2", |
||||||
|
"Coming Soon": "Em breve", |
||||||
|
"Error": "Erro", |
||||||
|
"Not Authorized": "Não autorizado", |
||||||
|
"Maintenance": "Manutenção", |
||||||
|
"Profile": "Perfil", |
||||||
|
"FAQ": "Perguntas frequentes", |
||||||
|
"Knowledge Base": "Base de Conhecimento", |
||||||
|
"Search": "Procurar", |
||||||
|
"Account Settings": "Configurações da conta", |
||||||
|
"Invoice": "Fatura", |
||||||
|
"Swiper": "Swiper", |
||||||
|
"Miscellaneous": "Diversas", |
||||||
|
"Charts & Maps": "Gráficos e Mapas", |
||||||
|
"Charts": "Gráficos", |
||||||
|
"Apex": "Ápice", |
||||||
|
"ChartJS": "ChartJS", |
||||||
|
"Recharts": "Recharts", |
||||||
|
"Leaflet Maps": "Leaflet Maps", |
||||||
|
"Extensions": "Extensões", |
||||||
|
"Sweet Alert": "Alerta Doce", |
||||||
|
"Toastr": "Toastr", |
||||||
|
"Sliders": "Sliders", |
||||||
|
"File Uploader": "Uploader de arquivos", |
||||||
|
"Editor": "Editor", |
||||||
|
"Tree": "árvore", |
||||||
|
"Drag & Drop": "Arraste e solte", |
||||||
|
"Tour": "Tour", |
||||||
|
"Auto Complete": "Autocompletar", |
||||||
|
"Clipboard": "Prancheta", |
||||||
|
"React Player": "Reagir de mídia", |
||||||
|
"Context Menu": "Menu contextual", |
||||||
|
"I18n": "I18n", |
||||||
|
"React Paginate": "React Paginate", |
||||||
|
"Export": "Exportação", |
||||||
|
"Import": "Importar", |
||||||
|
"Export Selected": "Exportar selecionado", |
||||||
|
"Access Control": "Controle de acesso", |
||||||
|
"Others": "Outras", |
||||||
|
"Menu Levels": "Níveis de Menu", |
||||||
|
"Second Level": "Segundo nível", |
||||||
|
"Second Level 2.1": "Segundo nível 2.1", |
||||||
|
"Second Level 2.2": "Segundo nível 2.2", |
||||||
|
"Third Level": "Terceiro nivel", |
||||||
|
"Third Level 3.1": "Terceiro nivel 3.1", |
||||||
|
"Third Level 3.2": "Terceiro nivel 3.2", |
||||||
|
"Disabled Menu": "Menu desativado", |
||||||
|
"Documentation": "Documentação", |
||||||
|
"Raise Support": "Levantar Suporte", |
||||||
|
"Change Log": "Log de alterações", |
||||||
|
"text": "O sésamo do bolo agarra dinamarquês do pão-de-espécie do queque eu amo o pão-de-espécie. Torta de torta de maçã jujuba chupa chups muffin halvah pirulito. Ameixa do açúcar do maçapão do tiramisu do bolo da aveia do bolo de chocolate. Bolo de aveia de torta doce donut dragée fruitcake algodão doce gotas de limão.", |
||||||
|
"Pricing": "Preços", |
||||||
|
"Blog": "Blog", |
||||||
|
"Detail": "Detalhes", |
||||||
|
"Form Repeater": "Repetidor de formulários", |
||||||
|
"Preview": "Pré-visualização", |
||||||
|
"Add": "Adicionar", |
||||||
|
"Ratings": "Avaliações", |
||||||
|
"show": "mostrar", |
||||||
|
"entries": "entradas", |
||||||
|
"search": "procurar", |
||||||
|
"Prev": "Anterior", |
||||||
|
"Next": "Próximo", |
||||||
|
"BlockUI": "BlockUI", |
||||||
|
"Reactstrap": "Reactstrap", |
||||||
|
"Welcome": "Bem-vinda", |
||||||
|
"Reset Password": "Redefinir senha", |
||||||
|
"Verify Email": "Verificar e-mail", |
||||||
|
"Deactivate Account": "Desativar conta", |
||||||
|
"Promotional": "Promocional", |
||||||
|
"Apps & Pages": "Aplicativos e páginas", |
||||||
|
"User Interface": "Interface de usuário", |
||||||
|
"Misc": "Misc" |
||||||
|
} |
Binary file not shown.
After Width: | Height: | Size: 209 KiB |
Binary file not shown.
Binary file not shown.
@ -0,0 +1,568 @@ |
|||||||
|
|
||||||
|
@font-face { |
||||||
|
font-family: "feather"; |
||||||
|
src: url('fonts/feather.eot?t=1525787366991'); /* IE9*/ |
||||||
|
src: url('fonts/feather.eot?t=1525787366991#iefix') format('embedded-opentype'), /* IE6-IE8 */ |
||||||
|
url('fonts/feather.woff?t=1525787366991') format('woff'), /* chrome, firefox */ |
||||||
|
url('fonts/feather.ttf?t=1525787366991') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+*/ |
||||||
|
url('fonts/feather.svg?t=1525787366991#feather') format('svg'); /* iOS 4.1- */ |
||||||
|
} |
||||||
|
|
||||||
|
.feather { |
||||||
|
/* use !important to prevent issues with browser extensions that change fonts */ |
||||||
|
font-family: 'feather' !important; |
||||||
|
speak: none; |
||||||
|
font-style: normal; |
||||||
|
font-weight: normal; |
||||||
|
font-variant: normal; |
||||||
|
text-transform: none; |
||||||
|
line-height: 1; |
||||||
|
|
||||||
|
/* Better Font Rendering =========== */ |
||||||
|
-webkit-font-smoothing: antialiased; |
||||||
|
-moz-osx-font-smoothing: grayscale; |
||||||
|
} |
||||||
|
|
||||||
|
.icon-alert-octagon:before { content: "\e81b"; } |
||||||
|
|
||||||
|
.icon-alert-circle:before { content: "\e81c"; } |
||||||
|
|
||||||
|
.icon-activity:before { content: "\e81d"; } |
||||||
|
|
||||||
|
.icon-alert-triangle:before { content: "\e81e"; } |
||||||
|
|
||||||
|
.icon-align-center:before { content: "\e81f"; } |
||||||
|
|
||||||
|
.icon-airplay:before { content: "\e820"; } |
||||||
|
|
||||||
|
.icon-align-justify:before { content: "\e821"; } |
||||||
|
|
||||||
|
.icon-align-left:before { content: "\e822"; } |
||||||
|
|
||||||
|
.icon-align-right:before { content: "\e823"; } |
||||||
|
|
||||||
|
.icon-arrow-down-left:before { content: "\e824"; } |
||||||
|
|
||||||
|
.icon-arrow-down-right:before { content: "\e825"; } |
||||||
|
|
||||||
|
.icon-anchor:before { content: "\e826"; } |
||||||
|
|
||||||
|
.icon-aperture:before { content: "\e827"; } |
||||||
|
|
||||||
|
.icon-arrow-left:before { content: "\e828"; } |
||||||
|
|
||||||
|
.icon-arrow-right:before { content: "\e829"; } |
||||||
|
|
||||||
|
.icon-arrow-down:before { content: "\e82a"; } |
||||||
|
|
||||||
|
.icon-arrow-up-left:before { content: "\e82b"; } |
||||||
|
|
||||||
|
.icon-arrow-up-right:before { content: "\e82c"; } |
||||||
|
|
||||||
|
.icon-arrow-up:before { content: "\e82d"; } |
||||||
|
|
||||||
|
.icon-award:before { content: "\e82e"; } |
||||||
|
|
||||||
|
.icon-bar-chart:before { content: "\e82f"; } |
||||||
|
|
||||||
|
.icon-at-sign:before { content: "\e830"; } |
||||||
|
|
||||||
|
.icon-bar-chart-2:before { content: "\e831"; } |
||||||
|
|
||||||
|
.icon-battery-charging:before { content: "\e832"; } |
||||||
|
|
||||||
|
.icon-bell-off:before { content: "\e833"; } |
||||||
|
|
||||||
|
.icon-battery:before { content: "\e834"; } |
||||||
|
|
||||||
|
.icon-bluetooth:before { content: "\e835"; } |
||||||
|
|
||||||
|
.icon-bell:before { content: "\e836"; } |
||||||
|
|
||||||
|
.icon-book:before { content: "\e837"; } |
||||||
|
|
||||||
|
.icon-briefcase:before { content: "\e838"; } |
||||||
|
|
||||||
|
.icon-camera-off:before { content: "\e839"; } |
||||||
|
|
||||||
|
.icon-calendar:before { content: "\e83a"; } |
||||||
|
|
||||||
|
.icon-bookmark:before { content: "\e83b"; } |
||||||
|
|
||||||
|
.icon-box:before { content: "\e83c"; } |
||||||
|
|
||||||
|
.icon-camera:before { content: "\e83d"; } |
||||||
|
|
||||||
|
.icon-check-circle:before { content: "\e83e"; } |
||||||
|
|
||||||
|
.icon-check:before { content: "\e83f"; } |
||||||
|
|
||||||
|
.icon-check-square:before { content: "\e840"; } |
||||||
|
|
||||||
|
.icon-cast:before { content: "\e841"; } |
||||||
|
|
||||||
|
.icon-chevron-down:before { content: "\e842"; } |
||||||
|
|
||||||
|
.icon-chevron-left:before { content: "\e843"; } |
||||||
|
|
||||||
|
.icon-chevron-right:before { content: "\e844"; } |
||||||
|
|
||||||
|
.icon-chevron-up:before { content: "\e845"; } |
||||||
|
|
||||||
|
.icon-chevrons-down:before { content: "\e846"; } |
||||||
|
|
||||||
|
.icon-chevrons-right:before { content: "\e847"; } |
||||||
|
|
||||||
|
.icon-chevrons-up:before { content: "\e848"; } |
||||||
|
|
||||||
|
.icon-chevrons-left:before { content: "\e849"; } |
||||||
|
|
||||||
|
.icon-circle:before { content: "\e84a"; } |
||||||
|
|
||||||
|
.icon-clipboard:before { content: "\e84b"; } |
||||||
|
|
||||||
|
.icon-chrome:before { content: "\e84c"; } |
||||||
|
|
||||||
|
.icon-clock:before { content: "\e84d"; } |
||||||
|
|
||||||
|
.icon-cloud-lightning:before { content: "\e84e"; } |
||||||
|
|
||||||
|
.icon-cloud-drizzle:before { content: "\e84f"; } |
||||||
|
|
||||||
|
.icon-cloud-rain:before { content: "\e850"; } |
||||||
|
|
||||||
|
.icon-cloud-off:before { content: "\e851"; } |
||||||
|
|
||||||
|
.icon-codepen:before { content: "\e852"; } |
||||||
|
|
||||||
|
.icon-cloud-snow:before { content: "\e853"; } |
||||||
|
|
||||||
|
.icon-compass:before { content: "\e854"; } |
||||||
|
|
||||||
|
.icon-copy:before { content: "\e855"; } |
||||||
|
|
||||||
|
.icon-corner-down-right:before { content: "\e856"; } |
||||||
|
|
||||||
|
.icon-corner-down-left:before { content: "\e857"; } |
||||||
|
|
||||||
|
.icon-corner-left-down:before { content: "\e858"; } |
||||||
|
|
||||||
|
.icon-corner-left-up:before { content: "\e859"; } |
||||||
|
|
||||||
|
.icon-corner-up-left:before { content: "\e85a"; } |
||||||
|
|
||||||
|
.icon-corner-up-right:before { content: "\e85b"; } |
||||||
|
|
||||||
|
.icon-corner-right-down:before { content: "\e85c"; } |
||||||
|
|
||||||
|
.icon-corner-right-up:before { content: "\e85d"; } |
||||||
|
|
||||||
|
.icon-cpu:before { content: "\e85e"; } |
||||||
|
|
||||||
|
.icon-credit-card:before { content: "\e85f"; } |
||||||
|
|
||||||
|
.icon-crosshair:before { content: "\e860"; } |
||||||
|
|
||||||
|
.icon-disc:before { content: "\e861"; } |
||||||
|
|
||||||
|
.icon-delete:before { content: "\e862"; } |
||||||
|
|
||||||
|
.icon-download-cloud:before { content: "\e863"; } |
||||||
|
|
||||||
|
.icon-download:before { content: "\e864"; } |
||||||
|
|
||||||
|
.icon-droplet:before { content: "\e865"; } |
||||||
|
|
||||||
|
.icon-edit-2:before { content: "\e866"; } |
||||||
|
|
||||||
|
.icon-edit:before { content: "\e867"; } |
||||||
|
|
||||||
|
.icon-edit-1:before { content: "\e868"; } |
||||||
|
|
||||||
|
.icon-external-link:before { content: "\e869"; } |
||||||
|
|
||||||
|
.icon-eye:before { content: "\e86a"; } |
||||||
|
|
||||||
|
.icon-feather:before { content: "\e86b"; } |
||||||
|
|
||||||
|
.icon-facebook:before { content: "\e86c"; } |
||||||
|
|
||||||
|
.icon-file-minus:before { content: "\e86d"; } |
||||||
|
|
||||||
|
.icon-eye-off:before { content: "\e86e"; } |
||||||
|
|
||||||
|
.icon-fast-forward:before { content: "\e86f"; } |
||||||
|
|
||||||
|
.icon-file-text:before { content: "\e870"; } |
||||||
|
|
||||||
|
.icon-film:before { content: "\e871"; } |
||||||
|
|
||||||
|
.icon-file:before { content: "\e872"; } |
||||||
|
|
||||||
|
.icon-file-plus:before { content: "\e873"; } |
||||||
|
|
||||||
|
.icon-folder:before { content: "\e874"; } |
||||||
|
|
||||||
|
.icon-filter:before { content: "\e875"; } |
||||||
|
|
||||||
|
.icon-flag:before { content: "\e876"; } |
||||||
|
|
||||||
|
.icon-globe:before { content: "\e877"; } |
||||||
|
|
||||||
|
.icon-grid:before { content: "\e878"; } |
||||||
|
|
||||||
|
.icon-heart:before { content: "\e879"; } |
||||||
|
|
||||||
|
.icon-home:before { content: "\e87a"; } |
||||||
|
|
||||||
|
.icon-github:before { content: "\e87b"; } |
||||||
|
|
||||||
|
.icon-image:before { content: "\e87c"; } |
||||||
|
|
||||||
|
.icon-inbox:before { content: "\e87d"; } |
||||||
|
|
||||||
|
.icon-layers:before { content: "\e87e"; } |
||||||
|
|
||||||
|
.icon-info:before { content: "\e87f"; } |
||||||
|
|
||||||
|
.icon-instagram:before { content: "\e880"; } |
||||||
|
|
||||||
|
.icon-layout:before { content: "\e881"; } |
||||||
|
|
||||||
|
.icon-link-2:before { content: "\e882"; } |
||||||
|
|
||||||
|
.icon-life-buoy:before { content: "\e883"; } |
||||||
|
|
||||||
|
.icon-link:before { content: "\e884"; } |
||||||
|
|
||||||
|
.icon-log-in:before { content: "\e885"; } |
||||||
|
|
||||||
|
.icon-list:before { content: "\e886"; } |
||||||
|
|
||||||
|
.icon-lock:before { content: "\e887"; } |
||||||
|
|
||||||
|
.icon-log-out:before { content: "\e888"; } |
||||||
|
|
||||||
|
.icon-loader:before { content: "\e889"; } |
||||||
|
|
||||||
|
.icon-mail:before { content: "\e88a"; } |
||||||
|
|
||||||
|
.icon-maximize-2:before { content: "\e88b"; } |
||||||
|
|
||||||
|
.icon-map:before { content: "\e88c"; } |
||||||
|
|
||||||
|
.icon-map-pin:before { content: "\e88e"; } |
||||||
|
|
||||||
|
.icon-menu:before { content: "\e88f"; } |
||||||
|
|
||||||
|
.icon-message-circle:before { content: "\e890"; } |
||||||
|
|
||||||
|
.icon-message-square:before { content: "\e891"; } |
||||||
|
|
||||||
|
.icon-minimize-2:before { content: "\e892"; } |
||||||
|
|
||||||
|
.icon-mic-off:before { content: "\e893"; } |
||||||
|
|
||||||
|
.icon-minus-circle:before { content: "\e894"; } |
||||||
|
|
||||||
|
.icon-mic:before { content: "\e895"; } |
||||||
|
|
||||||
|
.icon-minus-square:before { content: "\e896"; } |
||||||
|
|
||||||
|
.icon-minus:before { content: "\e897"; } |
||||||
|
|
||||||
|
.icon-moon:before { content: "\e898"; } |
||||||
|
|
||||||
|
.icon-monitor:before { content: "\e899"; } |
||||||
|
|
||||||
|
.icon-more-vertical:before { content: "\e89a"; } |
||||||
|
|
||||||
|
.icon-more-horizontal:before { content: "\e89b"; } |
||||||
|
|
||||||
|
.icon-move:before { content: "\e89c"; } |
||||||
|
|
||||||
|
.icon-music:before { content: "\e89d"; } |
||||||
|
|
||||||
|
.icon-navigation-2:before { content: "\e89e"; } |
||||||
|
|
||||||
|
.icon-navigation:before { content: "\e89f"; } |
||||||
|
|
||||||
|
.icon-octagon:before { content: "\e8a0"; } |
||||||
|
|
||||||
|
.icon-package:before { content: "\e8a1"; } |
||||||
|
|
||||||
|
.icon-pause-circle:before { content: "\e8a2"; } |
||||||
|
|
||||||
|
.icon-pause:before { content: "\e8a3"; } |
||||||
|
|
||||||
|
.icon-percent:before { content: "\e8a4"; } |
||||||
|
|
||||||
|
.icon-phone-call:before { content: "\e8a5"; } |
||||||
|
|
||||||
|
.icon-phone-forwarded:before { content: "\e8a6"; } |
||||||
|
|
||||||
|
.icon-phone-missed:before { content: "\e8a7"; } |
||||||
|
|
||||||
|
.icon-phone-off:before { content: "\e8a8"; } |
||||||
|
|
||||||
|
.icon-phone-incoming:before { content: "\e8a9"; } |
||||||
|
|
||||||
|
.icon-phone:before { content: "\e8aa"; } |
||||||
|
|
||||||
|
.icon-phone-outgoing:before { content: "\e8ab"; } |
||||||
|
|
||||||
|
.icon-pie-chart:before { content: "\e8ac"; } |
||||||
|
|
||||||
|
.icon-play-circle:before { content: "\e8ad"; } |
||||||
|
|
||||||
|
.icon-play:before { content: "\e8ae"; } |
||||||
|
|
||||||
|
.icon-plus-square:before { content: "\e8af"; } |
||||||
|
|
||||||
|
.icon-plus-circle:before { content: "\e8b0"; } |
||||||
|
|
||||||
|
.icon-plus:before { content: "\e8b1"; } |
||||||
|
|
||||||
|
.icon-pocket:before { content: "\e8b2"; } |
||||||
|
|
||||||
|
.icon-printer:before { content: "\e8b3"; } |
||||||
|
|
||||||
|
.icon-power:before { content: "\e8b4"; } |
||||||
|
|
||||||
|
.icon-radio:before { content: "\e8b5"; } |
||||||
|
|
||||||
|
.icon-repeat:before { content: "\e8b6"; } |
||||||
|
|
||||||
|
.icon-refresh-ccw:before { content: "\e8b7"; } |
||||||
|
|
||||||
|
.icon-rewind:before { content: "\e8b8"; } |
||||||
|
|
||||||
|
.icon-rotate-ccw:before { content: "\e8b9"; } |
||||||
|
|
||||||
|
.icon-refresh-cw:before { content: "\e8ba"; } |
||||||
|
|
||||||
|
.icon-rotate-cw:before { content: "\e8bb"; } |
||||||
|
|
||||||
|
.icon-save:before { content: "\e8bc"; } |
||||||
|
|
||||||
|
.icon-search:before { content: "\e8bd"; } |
||||||
|
|
||||||
|
.icon-server:before { content: "\e8be"; } |
||||||
|
|
||||||
|
.icon-scissors:before { content: "\e8bf"; } |
||||||
|
|
||||||
|
.icon-share-2:before { content: "\e8c0"; } |
||||||
|
|
||||||
|
.icon-share:before { content: "\e8c1"; } |
||||||
|
|
||||||
|
.icon-shield:before { content: "\e8c2"; } |
||||||
|
|
||||||
|
.icon-settings:before { content: "\e8c3"; } |
||||||
|
|
||||||
|
.icon-skip-back:before { content: "\e8c4"; } |
||||||
|
|
||||||
|
.icon-shuffle:before { content: "\e8c5"; } |
||||||
|
|
||||||
|
.icon-sidebar:before { content: "\e8c6"; } |
||||||
|
|
||||||
|
.icon-skip-forward:before { content: "\e8c7"; } |
||||||
|
|
||||||
|
.icon-slack:before { content: "\e8c8"; } |
||||||
|
|
||||||
|
.icon-slash:before { content: "\e8c9"; } |
||||||
|
|
||||||
|
.icon-smartphone:before { content: "\e8ca"; } |
||||||
|
|
||||||
|
.icon-square:before { content: "\e8cb"; } |
||||||
|
|
||||||
|
.icon-speaker:before { content: "\e8cc"; } |
||||||
|
|
||||||
|
.icon-star:before { content: "\e8cd"; } |
||||||
|
|
||||||
|
.icon-stop-circle:before { content: "\e8ce"; } |
||||||
|
|
||||||
|
.icon-sun:before { content: "\e8cf"; } |
||||||
|
|
||||||
|
.icon-sunrise:before { content: "\e8d0"; } |
||||||
|
|
||||||
|
.icon-tablet:before { content: "\e8d1"; } |
||||||
|
|
||||||
|
.icon-tag:before { content: "\e8d2"; } |
||||||
|
|
||||||
|
.icon-sunset:before { content: "\e8d3"; } |
||||||
|
|
||||||
|
.icon-target:before { content: "\e8d4"; } |
||||||
|
|
||||||
|
.icon-thermometer:before { content: "\e8d5"; } |
||||||
|
|
||||||
|
.icon-thumbs-up:before { content: "\e8d6"; } |
||||||
|
|
||||||
|
.icon-thumbs-down:before { content: "\e8d7"; } |
||||||
|
|
||||||
|
.icon-toggle-left:before { content: "\e8d8"; } |
||||||
|
|
||||||
|
.icon-toggle-right:before { content: "\e8d9"; } |
||||||
|
|
||||||
|
.icon-trash-2:before { content: "\e8da"; } |
||||||
|
|
||||||
|
.icon-trash:before { content: "\e8db"; } |
||||||
|
|
||||||
|
.icon-trending-up:before { content: "\e8dc"; } |
||||||
|
|
||||||
|
.icon-trending-down:before { content: "\e8dd"; } |
||||||
|
|
||||||
|
.icon-triangle:before { content: "\e8de"; } |
||||||
|
|
||||||
|
.icon-type:before { content: "\e8df"; } |
||||||
|
|
||||||
|
.icon-twitter:before { content: "\e8e0"; } |
||||||
|
|
||||||
|
.icon-upload:before { content: "\e8e1"; } |
||||||
|
|
||||||
|
.icon-umbrella:before { content: "\e8e2"; } |
||||||
|
|
||||||
|
.icon-upload-cloud:before { content: "\e8e3"; } |
||||||
|
|
||||||
|
.icon-unlock:before { content: "\e8e4"; } |
||||||
|
|
||||||
|
.icon-user-check:before { content: "\e8e5"; } |
||||||
|
|
||||||
|
.icon-user-minus:before { content: "\e8e6"; } |
||||||
|
|
||||||
|
.icon-user-plus:before { content: "\e8e7"; } |
||||||
|
|
||||||
|
.icon-user-x:before { content: "\e8e8"; } |
||||||
|
|
||||||
|
.icon-user:before { content: "\e8e9"; } |
||||||
|
|
||||||
|
.icon-users:before { content: "\e8ea"; } |
||||||
|
|
||||||
|
.icon-video-off:before { content: "\e8eb"; } |
||||||
|
|
||||||
|
.icon-video:before { content: "\e8ec"; } |
||||||
|
|
||||||
|
.icon-voicemail:before { content: "\e8ed"; } |
||||||
|
|
||||||
|
.icon-volume-x:before { content: "\e8ee"; } |
||||||
|
|
||||||
|
.icon-volume-2:before { content: "\e8ef"; } |
||||||
|
|
||||||
|
.icon-volume-1:before { content: "\e8f0"; } |
||||||
|
|
||||||
|
.icon-volume:before { content: "\e8f1"; } |
||||||
|
|
||||||
|
.icon-watch:before { content: "\e8f2"; } |
||||||
|
|
||||||
|
.icon-wifi:before { content: "\e8f3"; } |
||||||
|
|
||||||
|
.icon-x-square:before { content: "\e8f4"; } |
||||||
|
|
||||||
|
.icon-wind:before { content: "\e8f5"; } |
||||||
|
|
||||||
|
.icon-x:before { content: "\e8f6"; } |
||||||
|
|
||||||
|
.icon-x-circle:before { content: "\e8f7"; } |
||||||
|
|
||||||
|
.icon-zap:before { content: "\e8f8"; } |
||||||
|
|
||||||
|
.icon-zoom-in:before { content: "\e8f9"; } |
||||||
|
|
||||||
|
.icon-zoom-out:before { content: "\e8fa"; } |
||||||
|
|
||||||
|
.icon-command:before { content: "\e8fb"; } |
||||||
|
|
||||||
|
.icon-cloud:before { content: "\e8fc"; } |
||||||
|
|
||||||
|
.icon-hash:before { content: "\e8fd"; } |
||||||
|
|
||||||
|
.icon-headphones:before { content: "\e8fe"; } |
||||||
|
|
||||||
|
.icon-underline:before { content: "\e8ff"; } |
||||||
|
|
||||||
|
.icon-italic:before { content: "\e900"; } |
||||||
|
|
||||||
|
.icon-bold:before { content: "\e901"; } |
||||||
|
|
||||||
|
.icon-crop:before { content: "\e902"; } |
||||||
|
|
||||||
|
.icon-help-circle:before { content: "\e903"; } |
||||||
|
|
||||||
|
.icon-paperclip:before { content: "\e904"; } |
||||||
|
|
||||||
|
.icon-shopping-cart:before { content: "\e905"; } |
||||||
|
|
||||||
|
.icon-tv:before { content: "\e906"; } |
||||||
|
|
||||||
|
.icon-wifi-off:before { content: "\e907"; } |
||||||
|
|
||||||
|
.icon-minimize:before { content: "\e88d"; } |
||||||
|
|
||||||
|
.icon-maximize:before { content: "\e908"; } |
||||||
|
|
||||||
|
.icon-gitlab:before { content: "\e909"; } |
||||||
|
|
||||||
|
.icon-sliders:before { content: "\e90a"; } |
||||||
|
|
||||||
|
.icon-star-on:before { content: "\e90b"; } |
||||||
|
|
||||||
|
.icon-heart-on:before { content: "\e90c"; } |
||||||
|
|
||||||
|
.icon-archive:before { content: "\e90d"; } |
||||||
|
|
||||||
|
.icon-arrow-down-circle:before { content: "\e90e"; } |
||||||
|
|
||||||
|
.icon-arrow-up-circle:before { content: "\e90f"; } |
||||||
|
|
||||||
|
.icon-arrow-left-circle:before { content: "\e910"; } |
||||||
|
|
||||||
|
.icon-arrow-right-circle:before { content: "\e911"; } |
||||||
|
|
||||||
|
.icon-bar-chart-line-:before { content: "\e912"; } |
||||||
|
|
||||||
|
.icon-bar-chart-line:before { content: "\e913"; } |
||||||
|
|
||||||
|
.icon-book-open:before { content: "\e914"; } |
||||||
|
|
||||||
|
.icon-code:before { content: "\e915"; } |
||||||
|
|
||||||
|
.icon-database:before { content: "\e916"; } |
||||||
|
|
||||||
|
.icon-dollar-sign:before { content: "\e917"; } |
||||||
|
|
||||||
|
.icon-folder-plus:before { content: "\e918"; } |
||||||
|
|
||||||
|
.icon-gift:before { content: "\e919"; } |
||||||
|
|
||||||
|
.icon-folder-minus:before { content: "\e91a"; } |
||||||
|
|
||||||
|
.icon-git-commit:before { content: "\e91b"; } |
||||||
|
|
||||||
|
.icon-git-branch:before { content: "\e91c"; } |
||||||
|
|
||||||
|
.icon-git-pull-request:before { content: "\e91d"; } |
||||||
|
|
||||||
|
.icon-git-merge:before { content: "\e91e"; } |
||||||
|
|
||||||
|
.icon-linkedin:before { content: "\e91f"; } |
||||||
|
|
||||||
|
.icon-hard-drive:before { content: "\e920"; } |
||||||
|
|
||||||
|
.icon-more-vertical-:before { content: "\e921"; } |
||||||
|
|
||||||
|
.icon-more-horizontal-:before { content: "\e922"; } |
||||||
|
|
||||||
|
.icon-rss:before { content: "\e923"; } |
||||||
|
|
||||||
|
.icon-send:before { content: "\e924"; } |
||||||
|
|
||||||
|
.icon-shield-off:before { content: "\e925"; } |
||||||
|
|
||||||
|
.icon-shopping-bag:before { content: "\e926"; } |
||||||
|
|
||||||
|
.icon-terminal:before { content: "\e927"; } |
||||||
|
|
||||||
|
.icon-truck:before { content: "\e928"; } |
||||||
|
|
||||||
|
.icon-zap-off:before { content: "\e929"; } |
||||||
|
|
||||||
|
.icon-youtube:before { content: "\e92a"; } |
@ -0,0 +1,15 @@ |
|||||||
|
// ** Auth Endpoints
|
||||||
|
export default { |
||||||
|
loginEndpoint: '/jwt/login', |
||||||
|
registerEndpoint: '/jwt/register', |
||||||
|
refreshEndpoint: '/jwt/refresh-token', |
||||||
|
logoutEndpoint: '/jwt/logout', |
||||||
|
|
||||||
|
// ** This will be prefixed in authorization header with token
|
||||||
|
// ? e.g. Authorization: Bearer <token>
|
||||||
|
tokenType: 'Bearer', |
||||||
|
|
||||||
|
// ** Value of this property will be used as key to store JWT token in storage
|
||||||
|
storageTokenKeyName: 'accessToken', |
||||||
|
storageRefreshTokenKeyName: 'refreshToken' |
||||||
|
} |
@ -0,0 +1,108 @@ |
|||||||
|
import axios from 'axios' |
||||||
|
import jwtDefaultConfig from './jwtDefaultConfig' |
||||||
|
|
||||||
|
export default class JwtService { |
||||||
|
// ** jwtConfig <= Will be used by this service
|
||||||
|
jwtConfig = { ...jwtDefaultConfig } |
||||||
|
|
||||||
|
// ** For Refreshing Token
|
||||||
|
isAlreadyFetchingAccessToken = false |
||||||
|
|
||||||
|
// ** For Refreshing Token
|
||||||
|
subscribers = [] |
||||||
|
|
||||||
|
constructor(jwtOverrideConfig) { |
||||||
|
this.jwtConfig = { ...this.jwtConfig, ...jwtOverrideConfig } |
||||||
|
|
||||||
|
// ** Request Interceptor
|
||||||
|
axios.interceptors.request.use( |
||||||
|
config => { |
||||||
|
// ** Get token from localStorage
|
||||||
|
const accessToken = this.getToken() |
||||||
|
|
||||||
|
// ** If token is present add it to request's Authorization Header
|
||||||
|
if (accessToken) { |
||||||
|
// ** eslint-disable-next-line no-param-reassign
|
||||||
|
config.headers.Authorization = `${this.jwtConfig.tokenType} ${accessToken}` |
||||||
|
} |
||||||
|
return config |
||||||
|
}, |
||||||
|
error => Promise.reject(error) |
||||||
|
) |
||||||
|
|
||||||
|
// ** Add request/response interceptor
|
||||||
|
axios.interceptors.response.use( |
||||||
|
response => response, |
||||||
|
error => { |
||||||
|
// ** const { config, response: { status } } = error
|
||||||
|
const { config, response } = error |
||||||
|
const originalRequest = config |
||||||
|
|
||||||
|
// ** if (status === 401) {
|
||||||
|
if (response && response.status === 401) { |
||||||
|
if (!this.isAlreadyFetchingAccessToken) { |
||||||
|
this.isAlreadyFetchingAccessToken = true |
||||||
|
this.refreshToken().then(r => { |
||||||
|
this.isAlreadyFetchingAccessToken = false |
||||||
|
|
||||||
|
// ** Update accessToken in localStorage
|
||||||
|
this.setToken(r.data.accessToken) |
||||||
|
this.setRefreshToken(r.data.refreshToken) |
||||||
|
|
||||||
|
this.onAccessTokenFetched(r.data.accessToken) |
||||||
|
}) |
||||||
|
} |
||||||
|
const retryOriginalRequest = new Promise(resolve => { |
||||||
|
this.addSubscriber(accessToken => { |
||||||
|
// ** Make sure to assign accessToken according to your response.
|
||||||
|
// ** Check: https://pixinvent.ticksy.com/ticket/2413870
|
||||||
|
// ** Change Authorization header
|
||||||
|
originalRequest.headers.Authorization = `${this.jwtConfig.tokenType} ${accessToken}` |
||||||
|
resolve(this.axios(originalRequest)) |
||||||
|
}) |
||||||
|
}) |
||||||
|
return retryOriginalRequest |
||||||
|
} |
||||||
|
return Promise.reject(error) |
||||||
|
} |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
onAccessTokenFetched(accessToken) { |
||||||
|
this.subscribers = this.subscribers.filter(callback => callback(accessToken)) |
||||||
|
} |
||||||
|
|
||||||
|
addSubscriber(callback) { |
||||||
|
this.subscribers.push(callback) |
||||||
|
} |
||||||
|
|
||||||
|
getToken() { |
||||||
|
return localStorage.getItem(this.jwtConfig.storageTokenKeyName) |
||||||
|
} |
||||||
|
|
||||||
|
getRefreshToken() { |
||||||
|
return localStorage.getItem(this.jwtConfig.storageRefreshTokenKeyName) |
||||||
|
} |
||||||
|
|
||||||
|
setToken(value) { |
||||||
|
localStorage.setItem(this.jwtConfig.storageTokenKeyName, value) |
||||||
|
} |
||||||
|
|
||||||
|
setRefreshToken(value) { |
||||||
|
localStorage.setItem(this.jwtConfig.storageRefreshTokenKeyName, value) |
||||||
|
} |
||||||
|
|
||||||
|
login(...args) { |
||||||
|
return axios.post(this.jwtConfig.loginEndpoint, ...args) |
||||||
|
} |
||||||
|
|
||||||
|
register(...args) { |
||||||
|
return axios.post(this.jwtConfig.registerEndpoint, ...args) |
||||||
|
} |
||||||
|
|
||||||
|
refreshToken() { |
||||||
|
return axios.post(this.jwtConfig.refreshEndpoint, { |
||||||
|
refreshToken: this.getRefreshToken() |
||||||
|
}) |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,11 @@ |
|||||||
|
// ** JWT Service Import
|
||||||
|
import JwtService from './jwtService' |
||||||
|
|
||||||
|
// ** Export Service as useJwt
|
||||||
|
export default function useJwt(jwtOverrideConfig) { |
||||||
|
const jwt = new JwtService(jwtOverrideConfig) |
||||||
|
|
||||||
|
return { |
||||||
|
jwt |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,120 @@ |
|||||||
|
// ** React Imports
|
||||||
|
import { useState } from 'react' |
||||||
|
|
||||||
|
// ** Third Party Components
|
||||||
|
import Proptypes from 'prop-types' |
||||||
|
import classnames from 'classnames' |
||||||
|
import { ChevronUp } from 'react-feather' |
||||||
|
import { Collapse, Card, CardHeader, CardBody, CardTitle } from 'reactstrap' |
||||||
|
|
||||||
|
const AppCollapse = props => { |
||||||
|
// ** Props
|
||||||
|
const { data, type, accordion, active, toggle, titleKey, contentKey, className } = props |
||||||
|
|
||||||
|
/** |
||||||
|
** If accordion is true then return only one active index else return an Array |
||||||
|
*/ |
||||||
|
const defaultActive = () => { |
||||||
|
if (accordion) { |
||||||
|
return active |
||||||
|
} else { |
||||||
|
return [...active] |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// ** State
|
||||||
|
const [openCollapse, setOpenCollapse] = useState(defaultActive()) |
||||||
|
|
||||||
|
// ** Function to handle Collapse Toggle
|
||||||
|
const handleCollapseToggle = id => { |
||||||
|
if (accordion) { |
||||||
|
if (id === openCollapse) { |
||||||
|
setOpenCollapse(null) |
||||||
|
} else { |
||||||
|
setOpenCollapse(id) |
||||||
|
} |
||||||
|
} else { |
||||||
|
const arr = openCollapse, |
||||||
|
index = arr.indexOf(id) |
||||||
|
if (arr.includes(id)) { |
||||||
|
arr.splice(index, 1) |
||||||
|
setOpenCollapse([...arr]) |
||||||
|
} else { |
||||||
|
arr.push(id) |
||||||
|
setOpenCollapse([...arr]) |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// ** Function to render collapse
|
||||||
|
const renderData = () => { |
||||||
|
return data.map((item, index) => { |
||||||
|
const title = titleKey ? item[titleKey] : item.title, |
||||||
|
content = contentKey ? item[contentKey] : item.content |
||||||
|
|
||||||
|
return ( |
||||||
|
<Card |
||||||
|
className={classnames('app-collapse', { |
||||||
|
[item.className]: item.className, |
||||||
|
open: accordion ? openCollapse === index : openCollapse.includes(index) && type === 'shadow' |
||||||
|
})} |
||||||
|
key={index} |
||||||
|
> |
||||||
|
<CardHeader |
||||||
|
className={classnames('align-items-center', { |
||||||
|
collapsed: accordion ? openCollapse !== index : !openCollapse.includes(index) |
||||||
|
})} |
||||||
|
/*eslint-disable */ |
||||||
|
{...(toggle === 'hover' |
||||||
|
? { |
||||||
|
onMouseEnter: () => handleCollapseToggle(index) |
||||||
|
} |
||||||
|
: { |
||||||
|
onClick: () => handleCollapseToggle(index) |
||||||
|
})} |
||||||
|
/*eslint-enable */ |
||||||
|
> |
||||||
|
<CardTitle className='collapse-title'>{title}</CardTitle> |
||||||
|
<ChevronUp size={14} /> |
||||||
|
</CardHeader> |
||||||
|
<Collapse isOpen={accordion ? openCollapse === index : openCollapse.includes(index)}> |
||||||
|
<CardBody>{content}</CardBody> |
||||||
|
</Collapse> |
||||||
|
</Card> |
||||||
|
) |
||||||
|
}) |
||||||
|
} |
||||||
|
|
||||||
|
return ( |
||||||
|
<div |
||||||
|
className={classnames('collapse-icon', { |
||||||
|
[className]: className, |
||||||
|
'collapse-default': !type, |
||||||
|
'collapse-shadow': type === 'shadow', |
||||||
|
'collapse-border': type === 'border', |
||||||
|
'collapse-margin': type === 'margin' |
||||||
|
})} |
||||||
|
> |
||||||
|
{renderData()} |
||||||
|
</div> |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
export default AppCollapse |
||||||
|
|
||||||
|
// ** PropTypes
|
||||||
|
AppCollapse.propTypes = { |
||||||
|
data: Proptypes.array.isRequired, |
||||||
|
accordion: Proptypes.bool, |
||||||
|
type: Proptypes.oneOf(['shadow', 'border', 'margin']), |
||||||
|
active: Proptypes.oneOfType([Proptypes.array, Proptypes.number]), |
||||||
|
titleKey: Proptypes.string, |
||||||
|
contentKey: Proptypes.string, |
||||||
|
className: Proptypes.string |
||||||
|
} |
||||||
|
|
||||||
|
// ** Default Props
|
||||||
|
AppCollapse.defaultProps = { |
||||||
|
active: [], |
||||||
|
toggle: 'click' |
||||||
|
} |
@ -0,0 +1,85 @@ |
|||||||
|
// Component: Autocomplete |
||||||
|
// ======================================================================== |
||||||
|
|
||||||
|
@import '../../scss/base/bootstrap-extended/include'; |
||||||
|
@import '../../scss/base/components/include'; |
||||||
|
|
||||||
|
$autocomplete-active-color: #f1f1f1; |
||||||
|
|
||||||
|
.autocomplete-container { |
||||||
|
position: relative; |
||||||
|
.autocomplete-search { |
||||||
|
height: 100%; |
||||||
|
width: 100%; |
||||||
|
background-color: $white; |
||||||
|
&:focus { |
||||||
|
box-shadow: none; |
||||||
|
} |
||||||
|
} |
||||||
|
.suggestions-list { |
||||||
|
z-index: 998; |
||||||
|
list-style: none; |
||||||
|
padding-left: 0; |
||||||
|
border-radius: 0.5rem; |
||||||
|
max-height: 450px; |
||||||
|
height: auto; |
||||||
|
width: 100%; |
||||||
|
position: absolute; |
||||||
|
margin-top: 0.5rem; |
||||||
|
list-style-type: none; |
||||||
|
background-color: $white; |
||||||
|
box-shadow: 0 15px 30px 0 rgba(0, 0, 0, 0.11), 0 5px 15px 0 rgba(0, 0, 0, 0.08); |
||||||
|
.suggestion-item { |
||||||
|
padding: 0.9rem 1rem; |
||||||
|
color: $body-color; |
||||||
|
line-height: 1 !important; |
||||||
|
a { |
||||||
|
color: $body-color; |
||||||
|
} |
||||||
|
&.suggestion-title { |
||||||
|
font-size: 0.85rem; |
||||||
|
color: $text-muted; |
||||||
|
text-transform: uppercase; |
||||||
|
letter-spacing: 0.6px; |
||||||
|
margin-top: 0.75rem; |
||||||
|
margin-bottom: 0; |
||||||
|
} |
||||||
|
&.active, |
||||||
|
&:hover:not(.suggestion-title-wrapper):not(.no-result) { |
||||||
|
background-color: $autocomplete-active-color; |
||||||
|
color: $body-color; |
||||||
|
} |
||||||
|
|
||||||
|
&:hover:not(.suggestion-title-wrapper):not(.no-result) { |
||||||
|
cursor: pointer; |
||||||
|
} |
||||||
|
} |
||||||
|
&.open-up { |
||||||
|
top: auto; |
||||||
|
bottom: 100%; |
||||||
|
margin-top: 0; |
||||||
|
margin-bottom: 0.5rem; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// Dark |
||||||
|
.dark-layout { |
||||||
|
.autocomplete-container { |
||||||
|
.suggestions-list { |
||||||
|
background-color: $theme-dark-card-bg; |
||||||
|
.suggestion-item { |
||||||
|
color: $theme-dark-body-color !important; |
||||||
|
&.suggestion-title-wrapper { |
||||||
|
color: $theme-dark-text-muted-color; |
||||||
|
} |
||||||
|
&:not(.suggestion-title-wrapper) { |
||||||
|
&.active, |
||||||
|
&:hover { |
||||||
|
background-color: $theme-dark-body-bg !important; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,354 @@ |
|||||||
|
// ** React Imports
|
||||||
|
import { Fragment, useEffect, useState, useRef } from 'react' |
||||||
|
import ReactDOM from 'react-dom' |
||||||
|
import { useHistory } from 'react-router-dom' |
||||||
|
|
||||||
|
// ** Third Party Components
|
||||||
|
import PropTypes from 'prop-types' |
||||||
|
import classnames from 'classnames' |
||||||
|
import { AlertCircle } from 'react-feather' |
||||||
|
import PerfectScrollbar from 'react-perfect-scrollbar' |
||||||
|
|
||||||
|
// ** Custom Hooks
|
||||||
|
import { useOnClickOutside } from '@hooks/useOnClickOutside' |
||||||
|
|
||||||
|
// ** Styles
|
||||||
|
import '@styles/base/bootstrap-extended/_include.scss' |
||||||
|
import './autocomplete.scss' |
||||||
|
|
||||||
|
const Autocomplete = props => { |
||||||
|
// ** Refs
|
||||||
|
const container = useRef(null) |
||||||
|
const inputElRef = useRef(null) |
||||||
|
const suggestionsListRef = useRef(null) |
||||||
|
|
||||||
|
// ** States
|
||||||
|
const [focused, setFocused] = useState(false) |
||||||
|
const [activeSuggestion, setActiveSuggestion] = useState(0) |
||||||
|
const [showSuggestions, setShowSuggestions] = useState(false) |
||||||
|
const [userInput, setUserInput] = useState(props.value ? props.value : '') |
||||||
|
|
||||||
|
// ** Vars
|
||||||
|
const history = useHistory() |
||||||
|
let filteredData = [] |
||||||
|
|
||||||
|
// ** Suggestion Item Click Event
|
||||||
|
const onSuggestionItemClick = (url, e) => { |
||||||
|
setActiveSuggestion(0) |
||||||
|
setShowSuggestions(false) |
||||||
|
setUserInput(filteredData[activeSuggestion][props.filterKey]) |
||||||
|
if (url !== undefined && url !== null) { |
||||||
|
history.push(url) |
||||||
|
} |
||||||
|
|
||||||
|
if (props.onSuggestionClick) { |
||||||
|
props.onSuggestionClick(url, e) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// ** Suggestion Hover Event
|
||||||
|
const onSuggestionItemHover = index => { |
||||||
|
setActiveSuggestion(index) |
||||||
|
} |
||||||
|
|
||||||
|
// ** Input On Change Event
|
||||||
|
const onChange = e => { |
||||||
|
const userInput = e.currentTarget.value |
||||||
|
setActiveSuggestion(0) |
||||||
|
setShowSuggestions(true) |
||||||
|
setUserInput(userInput) |
||||||
|
if (e.target.value < 1) { |
||||||
|
setShowSuggestions(false) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// ** Input Click Event
|
||||||
|
const onInputClick = e => { |
||||||
|
e.stopPropagation() |
||||||
|
} |
||||||
|
|
||||||
|
// ** Input's Keydown Event
|
||||||
|
const onKeyDown = e => { |
||||||
|
const filterKey = props.filterKey |
||||||
|
const suggestionList = ReactDOM.findDOMNode(suggestionsListRef.current) |
||||||
|
|
||||||
|
// ** User pressed the up arrow
|
||||||
|
if (e.keyCode === 38 && activeSuggestion !== 0) { |
||||||
|
setActiveSuggestion(activeSuggestion - 1) |
||||||
|
|
||||||
|
if (e.target.value.length > -1 && suggestionList !== null && activeSuggestion <= filteredData.length / 2) { |
||||||
|
suggestionList.scrollTop = 0 |
||||||
|
} |
||||||
|
} else if (e.keyCode === 40 && activeSuggestion < filteredData.length - 1) { |
||||||
|
// ** User pressed the down arrow
|
||||||
|
setActiveSuggestion(activeSuggestion + 1) |
||||||
|
|
||||||
|
if (e.target.value.length > -1 && suggestionList !== null && activeSuggestion >= filteredData.length / 2) { |
||||||
|
suggestionList.scrollTop = suggestionList.scrollHeight |
||||||
|
} |
||||||
|
} else if (e.keyCode === 27) { |
||||||
|
// ** User Pressed ESC
|
||||||
|
setShowSuggestions(false) |
||||||
|
setUserInput('') |
||||||
|
} else if (e.keyCode === 13 && showSuggestions) { |
||||||
|
// ** User Pressed ENTER
|
||||||
|
onSuggestionItemClick(filteredData[activeSuggestion].link, e) |
||||||
|
setUserInput(filteredData[activeSuggestion][filterKey]) |
||||||
|
setShowSuggestions(false) |
||||||
|
} else { |
||||||
|
return |
||||||
|
} |
||||||
|
|
||||||
|
// ** Custom Keydown Event
|
||||||
|
if (props.onKeyDown !== undefined && props.onKeyDown !== null) { |
||||||
|
props.onKeyDown(e, userInput) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// ** Function To Render Grouped Suggestions
|
||||||
|
const renderGroupedSuggestion = arr => { |
||||||
|
const { filterKey, customRender } = props |
||||||
|
|
||||||
|
const renderSuggestion = (item, i) => { |
||||||
|
if (!customRender) { |
||||||
|
const suggestionURL = item.link !== undefined && item.link !== null ? item.link : null |
||||||
|
return ( |
||||||
|
<li |
||||||
|
className={classnames('suggestion-item', { |
||||||
|
active: filteredData.indexOf(item) === activeSuggestion |
||||||
|
})} |
||||||
|
key={item[filterKey]} |
||||||
|
onClick={e => onSuggestionItemClick(suggestionURL, e)} |
||||||
|
onMouseEnter={() => { |
||||||
|
onSuggestionItemHover(filteredData.indexOf(item)) |
||||||
|
}} |
||||||
|
> |
||||||
|
{item[filterKey]} |
||||||
|
</li> |
||||||
|
) |
||||||
|
} else if (customRender) { |
||||||
|
return customRender( |
||||||
|
item, |
||||||
|
i, |
||||||
|
filteredData, |
||||||
|
activeSuggestion, |
||||||
|
onSuggestionItemClick, |
||||||
|
onSuggestionItemHover, |
||||||
|
userInput |
||||||
|
) |
||||||
|
} else { |
||||||
|
return null |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return arr.map((item, i) => { |
||||||
|
return renderSuggestion(item, i) |
||||||
|
}) |
||||||
|
} |
||||||
|
|
||||||
|
// ** Function To Render Ungrouped Suggestions
|
||||||
|
const renderUngroupedSuggestions = () => { |
||||||
|
const { filterKey, suggestions, customRender, suggestionLimit } = props |
||||||
|
|
||||||
|
filteredData = [] |
||||||
|
const sortSingleData = suggestions |
||||||
|
.filter(i => { |
||||||
|
const startCondition = i[filterKey].toLowerCase().startsWith(userInput.toLowerCase()), |
||||||
|
includeCondition = i[filterKey].toLowerCase().includes(userInput.toLowerCase()) |
||||||
|
if (startCondition) { |
||||||
|
return startCondition |
||||||
|
} else if (!startCondition && includeCondition) { |
||||||
|
return includeCondition |
||||||
|
} else { |
||||||
|
return null |
||||||
|
} |
||||||
|
}) |
||||||
|
.slice(0, suggestionLimit) |
||||||
|
filteredData.push(...sortSingleData) |
||||||
|
if (sortSingleData.length) { |
||||||
|
return sortSingleData.map((suggestion, index) => { |
||||||
|
const suggestionURL = suggestion.link !== undefined && suggestion.link !== null ? suggestion.link : null |
||||||
|
if (!customRender) { |
||||||
|
return ( |
||||||
|
<li |
||||||
|
className={classnames('suggestion-item', { |
||||||
|
active: filteredData.indexOf(suggestion) === activeSuggestion |
||||||
|
})} |
||||||
|
key={suggestion[filterKey]} |
||||||
|
onClick={e => onSuggestionItemClick(suggestionURL, e)} |
||||||
|
onMouseEnter={() => onSuggestionItemHover(filteredData.indexOf(suggestion))} |
||||||
|
> |
||||||
|
{suggestion[filterKey]} |
||||||
|
</li> |
||||||
|
) |
||||||
|
} else if (customRender) { |
||||||
|
return customRender( |
||||||
|
suggestion, |
||||||
|
index, |
||||||
|
filteredData, |
||||||
|
activeSuggestion, |
||||||
|
onSuggestionItemClick, |
||||||
|
onSuggestionItemHover, |
||||||
|
userInput |
||||||
|
) |
||||||
|
} else { |
||||||
|
return null |
||||||
|
} |
||||||
|
}) |
||||||
|
} else { |
||||||
|
return ( |
||||||
|
<li className='suggestion-item no-result'> |
||||||
|
<AlertCircle size={15} /> <span className='align-middle ml-50'>No Result</span> |
||||||
|
</li> |
||||||
|
) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// ** Function To Render Suggestions
|
||||||
|
const renderSuggestions = () => { |
||||||
|
const { filterKey, grouped, filterHeaderKey, suggestions } = props |
||||||
|
|
||||||
|
// ** Checks if suggestions are grouped or not.
|
||||||
|
if (grouped === undefined || grouped === null || !grouped) { |
||||||
|
return renderUngroupedSuggestions() |
||||||
|
} else { |
||||||
|
filteredData = [] |
||||||
|
return suggestions.map(suggestion => { |
||||||
|
const sortData = suggestion.data |
||||||
|
.filter(i => { |
||||||
|
const startCondition = i[filterKey].toLowerCase().startsWith(userInput.toLowerCase()), |
||||||
|
includeCondition = i[filterKey].toLowerCase().includes(userInput.toLowerCase()) |
||||||
|
if (startCondition) { |
||||||
|
return startCondition |
||||||
|
} else if (!startCondition && includeCondition) { |
||||||
|
return includeCondition |
||||||
|
} else { |
||||||
|
return null |
||||||
|
} |
||||||
|
}) |
||||||
|
.slice(0, suggestion.searchLimit) |
||||||
|
|
||||||
|
filteredData.push(...sortData) |
||||||
|
return ( |
||||||
|
<Fragment key={suggestion[filterHeaderKey]}> |
||||||
|
<li className='suggestion-item suggestion-title-wrapper'> |
||||||
|
<h6 className='suggestion-title'>{suggestion[filterHeaderKey]}</h6> |
||||||
|
</li> |
||||||
|
{sortData.length ? ( |
||||||
|
renderGroupedSuggestion(sortData) |
||||||
|
) : ( |
||||||
|
<li className='suggestion-item no-result'> |
||||||
|
<AlertCircle size={15} /> <span className='align-middle ml-50'>No Result</span> |
||||||
|
</li> |
||||||
|
)} |
||||||
|
</Fragment> |
||||||
|
) |
||||||
|
}) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
//** ComponentDidMount
|
||||||
|
useEffect(() => { |
||||||
|
if (props.defaultSuggestions && focused) { |
||||||
|
setShowSuggestions(true) |
||||||
|
} |
||||||
|
}, [focused, props.defaultSuggestions]) |
||||||
|
|
||||||
|
//** ComponentDidUpdate
|
||||||
|
useEffect(() => { |
||||||
|
const textInput = ReactDOM.findDOMNode(inputElRef.current) |
||||||
|
|
||||||
|
// ** For searchbar focus
|
||||||
|
if (textInput !== null && props.autoFocus) { |
||||||
|
inputElRef.current.focus() |
||||||
|
} |
||||||
|
|
||||||
|
// ** If user has passed default suggestions & focus then show default suggestions
|
||||||
|
if (props.defaultSuggestions && focused) { |
||||||
|
setShowSuggestions(true) |
||||||
|
} |
||||||
|
|
||||||
|
// ** Function to run on user passed Clear Input
|
||||||
|
if (props.clearInput) { |
||||||
|
props.clearInput(userInput, setUserInput) |
||||||
|
} |
||||||
|
|
||||||
|
// ** Function on Suggestions Shown
|
||||||
|
if (props.onSuggestionsShown && showSuggestions) { |
||||||
|
props.onSuggestionsShown(userInput) |
||||||
|
} |
||||||
|
}, [setShowSuggestions, focused, userInput, showSuggestions, props]) |
||||||
|
|
||||||
|
// ** On External Click Close The Search & Call Passed Function
|
||||||
|
useOnClickOutside(container, () => { |
||||||
|
setShowSuggestions(false) |
||||||
|
if (props.externalClick) { |
||||||
|
props.externalClick() |
||||||
|
} |
||||||
|
}) |
||||||
|
|
||||||
|
let suggestionsListComponent |
||||||
|
|
||||||
|
if (showSuggestions) { |
||||||
|
suggestionsListComponent = ( |
||||||
|
<PerfectScrollbar |
||||||
|
className={classnames('suggestions-list', { |
||||||
|
[props.wrapperClass]: props.wrapperClass |
||||||
|
})} |
||||||
|
ref={suggestionsListRef} |
||||||
|
component='ul' |
||||||
|
options={{ wheelPropagation: false }} |
||||||
|
> |
||||||
|
{renderSuggestions()} |
||||||
|
</PerfectScrollbar> |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
return ( |
||||||
|
<div className='autocomplete-container' ref={container}> |
||||||
|
<input |
||||||
|
type='text' |
||||||
|
onChange={e => { |
||||||
|
onChange(e) |
||||||
|
if (props.onChange) { |
||||||
|
props.onChange(e) |
||||||
|
} |
||||||
|
}} |
||||||
|
onKeyDown={e => onKeyDown(e)} |
||||||
|
value={userInput} |
||||||
|
className={`autocomplete-search ${props.className ? props.className : ''}`} |
||||||
|
placeholder={props.placeholder} |
||||||
|
onClick={onInputClick} |
||||||
|
ref={inputElRef} |
||||||
|
onFocus={e => setFocused(true)} |
||||||
|
autoFocus={props.autoFocus} |
||||||
|
onBlur={e => { |
||||||
|
if (props.onBlur) props.onBlur(e) |
||||||
|
setFocused(false) |
||||||
|
}} |
||||||
|
/> |
||||||
|
{suggestionsListComponent} |
||||||
|
</div> |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
export default Autocomplete |
||||||
|
|
||||||
|
// ** PropTypes
|
||||||
|
Autocomplete.propTypes = { |
||||||
|
suggestions: PropTypes.array.isRequired, |
||||||
|
filterKey: PropTypes.string.isRequired, |
||||||
|
defaultValue: PropTypes.string, |
||||||
|
wrapperClass: PropTypes.string, |
||||||
|
filterHeaderKey: PropTypes.string, |
||||||
|
placeholder: PropTypes.string, |
||||||
|
suggestionLimit: PropTypes.number, |
||||||
|
grouped: PropTypes.bool, |
||||||
|
autoFocus: PropTypes.bool, |
||||||
|
onKeyDown: PropTypes.func, |
||||||
|
onChange: PropTypes.func, |
||||||
|
onSuggestionsShown: PropTypes.func, |
||||||
|
onSuggestionItemClick: PropTypes.func, |
||||||
|
clearInput: PropTypes.func, |
||||||
|
externalClick: PropTypes.func |
||||||
|
} |
@ -0,0 +1,65 @@ |
|||||||
|
// ** React Imports
|
||||||
|
import { Fragment } from 'react' |
||||||
|
|
||||||
|
// ** Third Party Components
|
||||||
|
import Proptypes from 'prop-types' |
||||||
|
import classnames from 'classnames' |
||||||
|
import { UncontrolledTooltip } from 'reactstrap' |
||||||
|
|
||||||
|
// ** Custom Components
|
||||||
|
import Avatar from '@components/avatar' |
||||||
|
|
||||||
|
const AvatarGroup = props => { |
||||||
|
// ** Props
|
||||||
|
const { data, tag, className } = props |
||||||
|
|
||||||
|
// ** Conditional Tag
|
||||||
|
const Tag = tag ? tag : 'div' |
||||||
|
|
||||||
|
// ** Render Data
|
||||||
|
const renderData = () => { |
||||||
|
return data.map((item, i) => { |
||||||
|
const ItemTag = item.tag ? item.tag : 'div' |
||||||
|
return ( |
||||||
|
<Fragment key={i}> |
||||||
|
{item.title ? ( |
||||||
|
<UncontrolledTooltip placement={item.placement} target={item.title.split(' ').join('-')}> |
||||||
|
{item.title} |
||||||
|
</UncontrolledTooltip> |
||||||
|
) : null} |
||||||
|
{!item.meta ? ( |
||||||
|
<Avatar |
||||||
|
tag={ItemTag} |
||||||
|
className={classnames('pull-up', { |
||||||
|
[item.className]: item.className |
||||||
|
})} |
||||||
|
{...(item.title ? { id: item.title.split(' ').join('-') } : {})} |
||||||
|
title={undefined} |
||||||
|
meta={undefined} |
||||||
|
{...item} |
||||||
|
/> |
||||||
|
) : null} |
||||||
|
{item.meta ? <ItemTag className='d-flex align-items-center pl-1'>{item.meta}</ItemTag> : null} |
||||||
|
</Fragment> |
||||||
|
) |
||||||
|
}) |
||||||
|
} |
||||||
|
|
||||||
|
return ( |
||||||
|
<Tag |
||||||
|
className={classnames('avatar-group', { |
||||||
|
[className]: className |
||||||
|
})} |
||||||
|
> |
||||||
|
{renderData()} |
||||||
|
</Tag> |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
export default AvatarGroup |
||||||
|
|
||||||
|
// ** PropTypes
|
||||||
|
AvatarGroup.propTypes = { |
||||||
|
data: Proptypes.array.isRequired, |
||||||
|
tag: Proptypes.oneOfType([Proptypes.func, Proptypes.string]) |
||||||
|
} |
@ -0,0 +1,155 @@ |
|||||||
|
// ** React Imports
|
||||||
|
import { forwardRef } from 'react' |
||||||
|
|
||||||
|
// ** Third Party Components
|
||||||
|
import Proptypes from 'prop-types' |
||||||
|
import { Badge } from 'reactstrap' |
||||||
|
import classnames from 'classnames' |
||||||
|
|
||||||
|
const Avatar = forwardRef((props, ref) => { |
||||||
|
// ** Props
|
||||||
|
const { |
||||||
|
color, |
||||||
|
className, |
||||||
|
imgClassName, |
||||||
|
initials, |
||||||
|
size, |
||||||
|
badgeUp, |
||||||
|
content, |
||||||
|
icon, |
||||||
|
badgeColor, |
||||||
|
badgeText, |
||||||
|
img, |
||||||
|
imgHeight, |
||||||
|
imgWidth, |
||||||
|
status, |
||||||
|
tag: Tag, |
||||||
|
contentStyles, |
||||||
|
...rest |
||||||
|
} = props |
||||||
|
|
||||||
|
// ** Function to extract initials from content
|
||||||
|
const getInitials = str => { |
||||||
|
const results = [] |
||||||
|
const wordArray = str.split(' ') |
||||||
|
wordArray.forEach(e => { |
||||||
|
results.push(e[0]) |
||||||
|
}) |
||||||
|
return results.join('') |
||||||
|
} |
||||||
|
|
||||||
|
return ( |
||||||
|
<Tag |
||||||
|
className={classnames('avatar', { |
||||||
|
[className]: className, |
||||||
|
[`bg-${color}`]: color, |
||||||
|
[`avatar-${size}`]: size |
||||||
|
})} |
||||||
|
ref={ref} |
||||||
|
{...rest} |
||||||
|
> |
||||||
|
{img === false || img === undefined ? ( |
||||||
|
<span |
||||||
|
className={classnames('avatar-content', { |
||||||
|
'position-relative': badgeUp |
||||||
|
})} |
||||||
|
style={contentStyles} |
||||||
|
> |
||||||
|
{initials ? getInitials(content) : content} |
||||||
|
|
||||||
|
{icon ? icon : null} |
||||||
|
{badgeUp ? ( |
||||||
|
<Badge color={badgeColor ? badgeColor : 'primary'} className='badge-sm badge-up' pill> |
||||||
|
{badgeText ? badgeText : '0'} |
||||||
|
</Badge> |
||||||
|
) : null} |
||||||
|
</span> |
||||||
|
) : ( |
||||||
|
<img |
||||||
|
className={classnames({ |
||||||
|
[imgClassName]: imgClassName |
||||||
|
})} |
||||||
|
src={img} |
||||||
|
alt='avatarImg' |
||||||
|
height={imgHeight && !size ? imgHeight : 32} |
||||||
|
width={imgWidth && !size ? imgWidth : 32} |
||||||
|
/> |
||||||
|
)} |
||||||
|
{status ? ( |
||||||
|
<span |
||||||
|
className={classnames({ |
||||||
|
[`avatar-status-${status}`]: status, |
||||||
|
[`avatar-status-${size}`]: size |
||||||
|
})} |
||||||
|
></span> |
||||||
|
) : null} |
||||||
|
</Tag> |
||||||
|
) |
||||||
|
}) |
||||||
|
|
||||||
|
export default Avatar |
||||||
|
|
||||||
|
// ** PropTypes
|
||||||
|
Avatar.propTypes = { |
||||||
|
imgClassName: Proptypes.string, |
||||||
|
className: Proptypes.string, |
||||||
|
src: Proptypes.string, |
||||||
|
tag: Proptypes.oneOfType([Proptypes.func, Proptypes.string]), |
||||||
|
badgeUp: Proptypes.bool, |
||||||
|
content: Proptypes.string, |
||||||
|
icon: Proptypes.node, |
||||||
|
contentStyles: Proptypes.object, |
||||||
|
badgeText: Proptypes.string, |
||||||
|
imgHeight: Proptypes.oneOfType([Proptypes.string, Proptypes.number]), |
||||||
|
imgWidth: Proptypes.oneOfType([Proptypes.string, Proptypes.number]), |
||||||
|
size: Proptypes.oneOf(['sm', 'lg', 'xl']), |
||||||
|
status: Proptypes.oneOf(['online', 'offline', 'away', 'busy']), |
||||||
|
badgeColor: Proptypes.oneOf([ |
||||||
|
'primary', |
||||||
|
'secondary', |
||||||
|
'success', |
||||||
|
'danger', |
||||||
|
'info', |
||||||
|
'warning', |
||||||
|
'dark', |
||||||
|
'light-primary', |
||||||
|
'light-secondary', |
||||||
|
'light-success', |
||||||
|
'light-danger', |
||||||
|
'light-info', |
||||||
|
'light-warning', |
||||||
|
'light-dark' |
||||||
|
]), |
||||||
|
color: Proptypes.oneOf([ |
||||||
|
'primary', |
||||||
|
'secondary', |
||||||
|
'success', |
||||||
|
'danger', |
||||||
|
'info', |
||||||
|
'warning', |
||||||
|
'dark', |
||||||
|
'light-primary', |
||||||
|
'light-secondary', |
||||||
|
'light-success', |
||||||
|
'light-danger', |
||||||
|
'light-info', |
||||||
|
'light-warning', |
||||||
|
'light-dark' |
||||||
|
]), |
||||||
|
initials(props) { |
||||||
|
if (props['initials'] && props['content'] === undefined) { |
||||||
|
return new Error('content prop is required with initials prop.') |
||||||
|
} |
||||||
|
if (props['initials'] && typeof props['content'] !== 'string') { |
||||||
|
return new Error('content prop must be a string.') |
||||||
|
} |
||||||
|
if (typeof props['initials'] !== 'boolean' && props['initials'] !== undefined) { |
||||||
|
return new Error('initials must be a boolean!') |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// ** Default Props
|
||||||
|
Avatar.defaultProps = { |
||||||
|
tag: 'div' |
||||||
|
} |
@ -0,0 +1,92 @@ |
|||||||
|
// ** React Imports
|
||||||
|
import { Link } from 'react-router-dom' |
||||||
|
|
||||||
|
// ** Third Party Components
|
||||||
|
import Proptypes from 'prop-types' |
||||||
|
import { Grid, CheckSquare, MessageSquare, Mail, Calendar } from 'react-feather' |
||||||
|
import { |
||||||
|
Breadcrumb, |
||||||
|
BreadcrumbItem, |
||||||
|
UncontrolledButtonDropdown, |
||||||
|
DropdownMenu, |
||||||
|
DropdownItem, |
||||||
|
DropdownToggle |
||||||
|
} from 'reactstrap' |
||||||
|
|
||||||
|
const BreadCrumbs = props => { |
||||||
|
// ** Props
|
||||||
|
const { breadCrumbTitle, breadCrumbParent, breadCrumbParent2, breadCrumbParent3, breadCrumbActive } = props |
||||||
|
|
||||||
|
return ( |
||||||
|
<div className='content-header row'> |
||||||
|
<div className='content-header-left col-md-9 col-12 mb-2'> |
||||||
|
<div className='row breadcrumbs-top'> |
||||||
|
<div className='col-12'> |
||||||
|
{breadCrumbTitle ? <h2 className='content-header-title float-left mb-0'>{breadCrumbTitle}</h2> : ''} |
||||||
|
<div className='breadcrumb-wrapper vs-breadcrumbs d-sm-block d-none col-12'> |
||||||
|
<Breadcrumb> |
||||||
|
<BreadcrumbItem tag='li'> |
||||||
|
<Link to='/'>Home</Link> |
||||||
|
</BreadcrumbItem> |
||||||
|
<BreadcrumbItem tag='li' className='text-primary'> |
||||||
|
{breadCrumbParent} |
||||||
|
</BreadcrumbItem> |
||||||
|
{breadCrumbParent2 ? ( |
||||||
|
<BreadcrumbItem tag='li' className='text-primary'> |
||||||
|
{breadCrumbParent2} |
||||||
|
</BreadcrumbItem> |
||||||
|
) : ( |
||||||
|
'' |
||||||
|
)} |
||||||
|
{breadCrumbParent3 ? ( |
||||||
|
<BreadcrumbItem tag='li' className='text-primary'> |
||||||
|
{breadCrumbParent3} |
||||||
|
</BreadcrumbItem> |
||||||
|
) : ( |
||||||
|
'' |
||||||
|
)} |
||||||
|
<BreadcrumbItem tag='li' active> |
||||||
|
{breadCrumbActive} |
||||||
|
</BreadcrumbItem> |
||||||
|
</Breadcrumb> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
<div className='content-header-right text-md-right col-md-3 col-12 d-md-block d-none'> |
||||||
|
<div className='form-group breadcrum-right dropdown'> |
||||||
|
<UncontrolledButtonDropdown> |
||||||
|
<DropdownToggle color='primary' size='sm' className='btn-icon btn-round dropdown-toggle'> |
||||||
|
<Grid size={14} /> |
||||||
|
</DropdownToggle> |
||||||
|
<DropdownMenu tag='ul' right> |
||||||
|
<DropdownItem tag={Link} to='/apps/chat'> |
||||||
|
<CheckSquare className='mr-1' size={14} /> |
||||||
|
<span className='align-middle'>Todo</span> |
||||||
|
</DropdownItem> |
||||||
|
<DropdownItem tag={Link} to='/apps/chat'> |
||||||
|
<MessageSquare className='mr-1' size={14} /> |
||||||
|
<span className='align-middle'>Chat</span> |
||||||
|
</DropdownItem> |
||||||
|
<DropdownItem tag={Link} to='/apps/email'> |
||||||
|
<Mail className='mr-1' size={14} /> |
||||||
|
<span className='align-middle'>Email</span> |
||||||
|
</DropdownItem> |
||||||
|
<DropdownItem tag={Link} to='/apps/calendar'> |
||||||
|
<Calendar className='mr-1' size={14} /> |
||||||
|
<span className='align-middle'>Calendar</span> |
||||||
|
</DropdownItem> |
||||||
|
</DropdownMenu> |
||||||
|
</UncontrolledButtonDropdown> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
) |
||||||
|
} |
||||||
|
export default BreadCrumbs |
||||||
|
|
||||||
|
// ** PropTypes
|
||||||
|
BreadCrumbs.propTypes = { |
||||||
|
breadCrumbTitle: Proptypes.string.isRequired, |
||||||
|
breadCrumbActive: Proptypes.string.isRequired |
||||||
|
} |
@ -0,0 +1,132 @@ |
|||||||
|
// ** React Imports
|
||||||
|
import { Fragment, useState, useEffect } from 'react' |
||||||
|
|
||||||
|
// ** Third Party Components
|
||||||
|
import PropTypes from 'prop-types' |
||||||
|
import classnames from 'classnames' |
||||||
|
import UiLoader from '@components/ui-loader' |
||||||
|
import { ChevronDown, RotateCw, X } from 'react-feather' |
||||||
|
import { Card, CardHeader, CardTitle, Collapse, Spinner } from 'reactstrap' |
||||||
|
|
||||||
|
const CardActions = props => { |
||||||
|
// ** Props
|
||||||
|
const { title, actions, children, collapseIcon, reloadIcon, removeIcon, endReload } = props |
||||||
|
|
||||||
|
// ** States
|
||||||
|
const [reload, setReload] = useState(false) |
||||||
|
const [collapse, setCollapse] = useState(true) |
||||||
|
const [visibility, setVisibility] = useState(true) |
||||||
|
|
||||||
|
/** |
||||||
|
** If custom icon is defined then consider that else default icons |
||||||
|
*/ |
||||||
|
const Icons = { |
||||||
|
collapse: collapseIcon ? collapseIcon : ChevronDown, |
||||||
|
remove: removeIcon ? removeIcon : X, |
||||||
|
reload: reloadIcon ? reloadIcon : RotateCw |
||||||
|
} |
||||||
|
|
||||||
|
// ** Action to call
|
||||||
|
const callAction = action => { |
||||||
|
switch (action) { |
||||||
|
case 'collapse': |
||||||
|
return setCollapse(!collapse) |
||||||
|
case 'remove': |
||||||
|
return setVisibility(false) |
||||||
|
case 'reload': |
||||||
|
return setReload(true) |
||||||
|
default: |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// ** Renders card actions
|
||||||
|
const renderIcons = () => { |
||||||
|
/** |
||||||
|
** IF: user passes array of actions then loop through them & render all of the actions |
||||||
|
** ELSE: render single action |
||||||
|
*/ |
||||||
|
|
||||||
|
if (Array.isArray(actions)) { |
||||||
|
return actions.map((action, i) => { |
||||||
|
const Tag = Icons[action] |
||||||
|
return ( |
||||||
|
<Tag |
||||||
|
key={i} |
||||||
|
className={classnames('cursor-pointer', { |
||||||
|
'mr-50': i < actions.length - 1 |
||||||
|
})} |
||||||
|
size={15} |
||||||
|
onClick={() => callAction(action)} |
||||||
|
/> |
||||||
|
) |
||||||
|
}) |
||||||
|
} else { |
||||||
|
const Tag = Icons[actions] |
||||||
|
return <Tag className='cursor-pointer' size={15} onClick={() => callAction(actions)} /> |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// ** Ends reload
|
||||||
|
const removeReload = () => { |
||||||
|
setReload(false) |
||||||
|
} |
||||||
|
|
||||||
|
// ** If user passes endReload function call it.
|
||||||
|
useEffect(() => { |
||||||
|
if (reload) { |
||||||
|
endReload(removeReload) |
||||||
|
} |
||||||
|
}) |
||||||
|
|
||||||
|
// ** If user passes collapse action then return <Collapse> as Wrapper else return <Fragment>
|
||||||
|
const CollapseWrapper = actions === 'collapse' || actions.includes('collapse') ? Collapse : Fragment |
||||||
|
|
||||||
|
// ** If user passes reload action then return <BlockUi> as Wrapper else return <Fragment>
|
||||||
|
const BlockUiWrapper = actions === 'reload' || actions.includes('reload') ? UiLoader : Fragment |
||||||
|
|
||||||
|
return ( |
||||||
|
<BlockUiWrapper |
||||||
|
/*eslint-disable */ |
||||||
|
{...(actions === 'reload' || actions.includes('reload') |
||||||
|
? { |
||||||
|
blocking: reload |
||||||
|
} |
||||||
|
: {})} |
||||||
|
/*eslint-enable */ |
||||||
|
> |
||||||
|
<Card |
||||||
|
className={classnames('card-action', { |
||||||
|
'd-none': !visibility |
||||||
|
})} |
||||||
|
> |
||||||
|
<CardHeader> |
||||||
|
<CardTitle tag='h4'>{title}</CardTitle> |
||||||
|
<div className='action-icons'>{renderIcons()}</div> |
||||||
|
</CardHeader> |
||||||
|
<CollapseWrapper {...(actions === 'collapse' || actions.includes('collapse') ? { isOpen: collapse } : {})}> |
||||||
|
{children} |
||||||
|
</CollapseWrapper> |
||||||
|
</Card> |
||||||
|
</BlockUiWrapper> |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
export default CardActions |
||||||
|
|
||||||
|
// ** PropTypes
|
||||||
|
CardActions.propTypes = { |
||||||
|
title: PropTypes.string.isRequired, |
||||||
|
collapseIcon: PropTypes.any, |
||||||
|
removeIcon: PropTypes.any, |
||||||
|
reloadIcon: PropTypes.any, |
||||||
|
actions: PropTypes.oneOfType([PropTypes.string, PropTypes.arrayOf(PropTypes.string)]).isRequired, |
||||||
|
endReload(props) { |
||||||
|
// ** User passes reload action and doesn't pass endReload then return Error
|
||||||
|
if ( |
||||||
|
(props['actions'] === 'reload' && props['endReload'] === undefined) || |
||||||
|
(props['actions'].includes('reload') && props['endReload'] === undefined) |
||||||
|
) { |
||||||
|
return new Error('Please provide a function to end reload!') |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,51 @@ |
|||||||
|
// ** React Imports
|
||||||
|
import { Fragment, useState } from 'react' |
||||||
|
|
||||||
|
// ** Third Party Components
|
||||||
|
import PropTypes from 'prop-types' |
||||||
|
import { Code } from 'react-feather' |
||||||
|
import { Card, CardHeader, CardBody, CardTitle, Collapse } from 'reactstrap' |
||||||
|
|
||||||
|
const CardSnippet = props => { |
||||||
|
// ** Props
|
||||||
|
const { title, children, noBody, code, iconCode } = props |
||||||
|
|
||||||
|
// ** State
|
||||||
|
const [isOpen, setIsOpen] = useState(false) |
||||||
|
|
||||||
|
// ** If user passes custom icon then render that else render default icon
|
||||||
|
const IconCode = iconCode ? iconCode : <Code size={15} /> |
||||||
|
|
||||||
|
// ** To toggle collapse
|
||||||
|
const toggle = () => setIsOpen(!isOpen) |
||||||
|
|
||||||
|
// ** If user passes noBody then return <Fragment> else return <CardBody>
|
||||||
|
const Wrapper = noBody ? Fragment : CardBody |
||||||
|
|
||||||
|
return ( |
||||||
|
<Card className='card-snippet'> |
||||||
|
<CardHeader> |
||||||
|
<CardTitle tag='h4'>{title}</CardTitle> |
||||||
|
<div className='views cursor-pointer' onClick={toggle}> |
||||||
|
{IconCode} |
||||||
|
</div> |
||||||
|
</CardHeader> |
||||||
|
<Wrapper>{children}</Wrapper> |
||||||
|
<Collapse isOpen={isOpen}> |
||||||
|
<CardBody>{code}</CardBody> |
||||||
|
</Collapse> |
||||||
|
</Card> |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
export default CardSnippet |
||||||
|
|
||||||
|
// ** PropTypes
|
||||||
|
CardSnippet.propTypes = { |
||||||
|
className: PropTypes.string, |
||||||
|
title: PropTypes.string.isRequired, |
||||||
|
children: PropTypes.any, |
||||||
|
code: PropTypes.node, |
||||||
|
iconCode: PropTypes.node, |
||||||
|
noBody: PropTypes.bool |
||||||
|
} |
@ -0,0 +1,357 @@ |
|||||||
|
// ** React Imports
|
||||||
|
import { useState } from 'react' |
||||||
|
|
||||||
|
// ** Third Party Components
|
||||||
|
import Select from 'react-select' |
||||||
|
import classnames from 'classnames' |
||||||
|
import { Settings, X } from 'react-feather' |
||||||
|
import { CustomInput, FormGroup } from 'reactstrap' |
||||||
|
import PerfectScrollbar from 'react-perfect-scrollbar' |
||||||
|
import { selectThemeColors } from '@utils' |
||||||
|
|
||||||
|
// ** Styles
|
||||||
|
import '@styles/react/libs/react-select/_react-select.scss' |
||||||
|
|
||||||
|
const Customizer = props => { |
||||||
|
// ** Props
|
||||||
|
const { |
||||||
|
skin, |
||||||
|
setSkin, |
||||||
|
isRtl, |
||||||
|
setIsRtl, |
||||||
|
layout, |
||||||
|
setLayout, |
||||||
|
navbarType, |
||||||
|
setNavbarType, |
||||||
|
footerType, |
||||||
|
setFooterType, |
||||||
|
navbarColor, |
||||||
|
setNavbarColor, |
||||||
|
isHidden, |
||||||
|
setIsHidden, |
||||||
|
contentWidth, |
||||||
|
setContentWidth, |
||||||
|
menuCollapsed, |
||||||
|
setMenuCollapsed, |
||||||
|
transition, |
||||||
|
setTransition |
||||||
|
} = props |
||||||
|
|
||||||
|
// ** State
|
||||||
|
const [openCustomizer, setOpenCustomizer] = useState(false) |
||||||
|
|
||||||
|
// ** Toggles Customizer
|
||||||
|
const handleToggle = e => { |
||||||
|
e.preventDefault() |
||||||
|
setOpenCustomizer(!openCustomizer) |
||||||
|
} |
||||||
|
|
||||||
|
// ** Render Layout Skin Options
|
||||||
|
const renderSkinsRadio = () => { |
||||||
|
const skinsArr = [ |
||||||
|
{ |
||||||
|
name: 'light', |
||||||
|
label: 'Light', |
||||||
|
checked: skin === 'light' |
||||||
|
}, |
||||||
|
{ |
||||||
|
name: 'bordered', |
||||||
|
label: 'Bordered', |
||||||
|
checked: skin === 'bordered' |
||||||
|
}, |
||||||
|
{ |
||||||
|
name: 'dark', |
||||||
|
label: 'Dark', |
||||||
|
checked: skin === 'dark' |
||||||
|
}, |
||||||
|
{ |
||||||
|
name: 'semi-dark', |
||||||
|
label: 'Semi Dark', |
||||||
|
checked: skin === 'semi-dark' |
||||||
|
} |
||||||
|
] |
||||||
|
|
||||||
|
return skinsArr.map((radio, index) => { |
||||||
|
const marginCondition = index !== skinsArr.length - 1 |
||||||
|
|
||||||
|
if (layout === 'HorizontalLayout' && radio.name === 'semi-dark') { |
||||||
|
return null |
||||||
|
} |
||||||
|
|
||||||
|
return ( |
||||||
|
<CustomInput |
||||||
|
key={index} |
||||||
|
type='radio' |
||||||
|
id={radio.name} |
||||||
|
label={radio.label} |
||||||
|
checked={radio.checked} |
||||||
|
onChange={() => setSkin(radio.name)} |
||||||
|
className={classnames({ 'mr-1': marginCondition })} |
||||||
|
/> |
||||||
|
) |
||||||
|
}) |
||||||
|
} |
||||||
|
|
||||||
|
// ** Render Navbar Colors Options
|
||||||
|
const renderNavbarColors = () => { |
||||||
|
const colorsArr = ['white', 'primary', 'secondary', 'success', 'danger', 'info', 'warning', 'dark'] |
||||||
|
|
||||||
|
return colorsArr.map(color => ( |
||||||
|
<li |
||||||
|
key={color} |
||||||
|
className={classnames(`color-box bg-${color}`, { |
||||||
|
selected: navbarColor === color, |
||||||
|
border: color === 'white' |
||||||
|
})} |
||||||
|
onClick={() => setNavbarColor(color)} |
||||||
|
></li> |
||||||
|
)) |
||||||
|
} |
||||||
|
|
||||||
|
// ** Render Navbar Type Options
|
||||||
|
const renderNavbarTypeRadio = () => { |
||||||
|
const navbarTypeArr = [ |
||||||
|
{ |
||||||
|
name: 'floating', |
||||||
|
label: 'Floating', |
||||||
|
checked: navbarType === 'floating' |
||||||
|
}, |
||||||
|
{ |
||||||
|
name: 'sticky', |
||||||
|
label: 'Sticky', |
||||||
|
checked: navbarType === 'sticky' |
||||||
|
}, |
||||||
|
{ |
||||||
|
name: 'static', |
||||||
|
label: 'Static', |
||||||
|
checked: navbarType === 'static' |
||||||
|
}, |
||||||
|
{ |
||||||
|
name: 'hidden', |
||||||
|
label: 'Hidden', |
||||||
|
checked: navbarType === 'hidden' |
||||||
|
} |
||||||
|
] |
||||||
|
|
||||||
|
return navbarTypeArr.map((radio, index) => { |
||||||
|
const marginCondition = index !== navbarTypeArr.length - 1 |
||||||
|
|
||||||
|
if (layout === 'HorizontalLayout' && radio.name === 'hidden') { |
||||||
|
return null |
||||||
|
} |
||||||
|
|
||||||
|
return ( |
||||||
|
<CustomInput |
||||||
|
key={index} |
||||||
|
type='radio' |
||||||
|
id={radio.name} |
||||||
|
label={radio.label} |
||||||
|
checked={radio.checked} |
||||||
|
onChange={() => setNavbarType(radio.name)} |
||||||
|
className={classnames({ 'mr-1': marginCondition })} |
||||||
|
/> |
||||||
|
) |
||||||
|
}) |
||||||
|
} |
||||||
|
|
||||||
|
// ** Render Footer Type Options
|
||||||
|
const renderFooterTypeRadio = () => { |
||||||
|
const footerTypeArr = [ |
||||||
|
{ |
||||||
|
name: 'sticky', |
||||||
|
label: 'Sticky', |
||||||
|
checked: footerType === 'sticky' |
||||||
|
}, |
||||||
|
{ |
||||||
|
name: 'static', |
||||||
|
label: 'Static', |
||||||
|
checked: footerType === 'static' |
||||||
|
}, |
||||||
|
{ |
||||||
|
name: 'hidden', |
||||||
|
label: 'Hidden', |
||||||
|
checked: footerType === 'hidden' |
||||||
|
} |
||||||
|
] |
||||||
|
|
||||||
|
return footerTypeArr.map((radio, index) => { |
||||||
|
const marginCondition = index !== footerTypeArr.length - 1 |
||||||
|
|
||||||
|
return ( |
||||||
|
<CustomInput |
||||||
|
key={index} |
||||||
|
type='radio' |
||||||
|
id={`footer-${radio.name}`} |
||||||
|
label={radio.label} |
||||||
|
checked={radio.checked} |
||||||
|
onChange={() => setFooterType(radio.name)} |
||||||
|
className={classnames({ 'mr-1': marginCondition })} |
||||||
|
/> |
||||||
|
) |
||||||
|
}) |
||||||
|
} |
||||||
|
|
||||||
|
// ** Router Transition Options
|
||||||
|
const transitionOptions = [ |
||||||
|
{ value: 'fadeIn', label: 'Fade' }, |
||||||
|
{ value: 'fadeInLeft', label: 'Fade In Left' }, |
||||||
|
{ value: 'zoomIn', label: 'Zoom In' }, |
||||||
|
{ value: 'none', label: 'None' } |
||||||
|
] |
||||||
|
|
||||||
|
// ** Get Current Transition
|
||||||
|
const transitionValue = transitionOptions.find(i => i.value === transition) |
||||||
|
|
||||||
|
return ( |
||||||
|
<div |
||||||
|
className={classnames('customizer d-none d-md-block', { |
||||||
|
open: openCustomizer |
||||||
|
})} |
||||||
|
> |
||||||
|
<a href='/' className='customizer-toggle d-flex align-items-center justify-content-center' onClick={handleToggle}> |
||||||
|
<Settings size={14} className='spinner' /> |
||||||
|
</a> |
||||||
|
<PerfectScrollbar className='customizer-content'> |
||||||
|
<div className='customizer-header px-2 pt-1 pb-0 position-relative'> |
||||||
|
<h4 className='mb-0'>Theme Customizer</h4> |
||||||
|
<p className='m-0'>Customize & Preview in Real Time</p> |
||||||
|
<a href='/' className='customizer-close' onClick={handleToggle}> |
||||||
|
<X /> |
||||||
|
</a> |
||||||
|
</div> |
||||||
|
|
||||||
|
<hr /> |
||||||
|
|
||||||
|
<div className='px-2'> |
||||||
|
<FormGroup className='mb-2'> |
||||||
|
<p className='font-weight-bold'>Skin</p> |
||||||
|
<div className='d-flex'>{renderSkinsRadio()}</div> |
||||||
|
</FormGroup> |
||||||
|
|
||||||
|
<FormGroup className='mb-2'> |
||||||
|
<p className='font-weight-bold'>Content Width</p> |
||||||
|
<div className='d-flex'> |
||||||
|
<CustomInput |
||||||
|
type='radio' |
||||||
|
id='full-width' |
||||||
|
className='mr-1' |
||||||
|
label='Full Width' |
||||||
|
checked={contentWidth === 'full'} |
||||||
|
onChange={() => setContentWidth('full')} |
||||||
|
/> |
||||||
|
<CustomInput |
||||||
|
type='radio' |
||||||
|
id='boxes' |
||||||
|
label='Boxed' |
||||||
|
checked={contentWidth === 'boxed'} |
||||||
|
onChange={() => setContentWidth('boxed')} |
||||||
|
/> |
||||||
|
</div> |
||||||
|
</FormGroup> |
||||||
|
|
||||||
|
<FormGroup className='mb-2'> |
||||||
|
<div className='d-flex'> |
||||||
|
<p className='font-weight-bold mr-auto mb-0'>RTL</p> |
||||||
|
<CustomInput type='switch' id='rtl' name='RTL' checked={isRtl} onChange={() => setIsRtl(!isRtl)} /> |
||||||
|
</div> |
||||||
|
</FormGroup> |
||||||
|
|
||||||
|
<FormGroup className='mb-2'> |
||||||
|
<div className='d-flex justify-content-between align-items-center'> |
||||||
|
<p className='font-weight-bold mb-0'>Router Transition</p> |
||||||
|
<Select |
||||||
|
theme={selectThemeColors} |
||||||
|
className='react-select' |
||||||
|
classNamePrefix='select' |
||||||
|
defaultValue={transitionOptions[0]} |
||||||
|
value={transitionValue} |
||||||
|
options={transitionOptions} |
||||||
|
isClearable={false} |
||||||
|
onChange={({ value }) => setTransition(value)} |
||||||
|
/> |
||||||
|
</div> |
||||||
|
</FormGroup> |
||||||
|
</div> |
||||||
|
|
||||||
|
<hr /> |
||||||
|
|
||||||
|
<div className='px-2'> |
||||||
|
<p className='font-weight-bold'>Menu Layout</p> |
||||||
|
<FormGroup className='mb-2'> |
||||||
|
<div className='d-flex align-items-center'> |
||||||
|
<CustomInput |
||||||
|
type='radio' |
||||||
|
id='vertical-layout' |
||||||
|
label='Vertical' |
||||||
|
checked={layout === 'VerticalLayout'} |
||||||
|
onChange={() => setLayout('vertical')} |
||||||
|
className='mr-1' |
||||||
|
/> |
||||||
|
<CustomInput |
||||||
|
type='radio' |
||||||
|
id='horizontal-layout' |
||||||
|
label='Horizontal' |
||||||
|
checked={layout === 'HorizontalLayout'} |
||||||
|
onChange={() => setLayout('horizontal')} |
||||||
|
/> |
||||||
|
</div> |
||||||
|
</FormGroup> |
||||||
|
{layout !== 'HorizontalLayout' ? ( |
||||||
|
<FormGroup className='mb-2'> |
||||||
|
<div className='d-flex align-items-center'> |
||||||
|
<p className='font-weight-bold mr-auto mb-0'>Menu Collapsed</p> |
||||||
|
<CustomInput |
||||||
|
type='switch' |
||||||
|
id='menu-collapsed' |
||||||
|
name='menu-collapsed' |
||||||
|
checked={menuCollapsed} |
||||||
|
onChange={() => setMenuCollapsed(!menuCollapsed)} |
||||||
|
/> |
||||||
|
</div> |
||||||
|
</FormGroup> |
||||||
|
) : null} |
||||||
|
|
||||||
|
<FormGroup className='mb-2'> |
||||||
|
<div className='d-flex align-items-center'> |
||||||
|
<p className='font-weight-bold mr-auto mb-0'>Menu Hidden</p> |
||||||
|
<CustomInput |
||||||
|
type='switch' |
||||||
|
id='menu-hidden' |
||||||
|
name='menu-hidden' |
||||||
|
checked={isHidden} |
||||||
|
onChange={() => setIsHidden(!isHidden)} |
||||||
|
/> |
||||||
|
</div> |
||||||
|
</FormGroup> |
||||||
|
</div> |
||||||
|
|
||||||
|
<hr /> |
||||||
|
|
||||||
|
<div className='px-2'> |
||||||
|
{layout !== 'HorizontalLayout' ? ( |
||||||
|
<FormGroup className='mb-2'> |
||||||
|
<p className='font-weight-bold'>Navbar Color</p> |
||||||
|
<ul className='list-inline unstyled-list'>{renderNavbarColors()}</ul> |
||||||
|
</FormGroup> |
||||||
|
) : null} |
||||||
|
|
||||||
|
<FormGroup className='mb-2'> |
||||||
|
<p className='font-weight-bold'>{layout === 'HorizontalLayout' ? 'Menu' : 'Navbar'} Type</p> |
||||||
|
<div className='d-flex'>{renderNavbarTypeRadio()}</div> |
||||||
|
</FormGroup> |
||||||
|
</div> |
||||||
|
|
||||||
|
<hr /> |
||||||
|
|
||||||
|
<div className='px-2'> |
||||||
|
<FormGroup className='mb-2'> |
||||||
|
<p className='font-weight-bold'>Footer Type</p> |
||||||
|
<div className='d-flex'>{renderFooterTypeRadio()}</div> |
||||||
|
</FormGroup> |
||||||
|
</div> |
||||||
|
</PerfectScrollbar> |
||||||
|
</div> |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
export default Customizer |
@ -0,0 +1,30 @@ |
|||||||
|
// ** React Imports
|
||||||
|
import Proptypes from 'prop-types' |
||||||
|
import { Row, Col } from 'reactstrap' |
||||||
|
|
||||||
|
const ExtensionsHeader = props => { |
||||||
|
return ( |
||||||
|
<Row className='mb-2'> |
||||||
|
<Col sm='12' className='ml-50'> |
||||||
|
<p className='font-medium-5 mt-1 extension-title' data-tour='extension-title'> |
||||||
|
{props.title} |
||||||
|
</p> |
||||||
|
{props.link ? ( |
||||||
|
<a href={props.link} target='_blank' rel='noopener noreferrer'> |
||||||
|
{props.subTitle} |
||||||
|
</a> |
||||||
|
) : ( |
||||||
|
<p className='text-primary'>{props.subTitle}</p> |
||||||
|
)} |
||||||
|
</Col> |
||||||
|
</Row> |
||||||
|
) |
||||||
|
} |
||||||
|
export default ExtensionsHeader |
||||||
|
|
||||||
|
// ** PropTypes
|
||||||
|
ExtensionsHeader.propTypes = { |
||||||
|
title: Proptypes.string.isRequired, |
||||||
|
subTitle: Proptypes.string.isRequired, |
||||||
|
link: Proptypes.string |
||||||
|
} |
@ -0,0 +1,98 @@ |
|||||||
|
// ** React Imports
|
||||||
|
import { Fragment, useState } from 'react' |
||||||
|
|
||||||
|
// ** Third Party Components
|
||||||
|
import PropTypes from 'prop-types' |
||||||
|
import classnames from 'classnames' |
||||||
|
import { Eye, EyeOff } from 'react-feather' |
||||||
|
import { InputGroup, InputGroupAddon, Input, InputGroupText, Label, inputClassName } from 'reactstrap' |
||||||
|
|
||||||
|
const InputPasswordToggle = props => { |
||||||
|
// ** Props
|
||||||
|
const { |
||||||
|
label, |
||||||
|
hideIcon, |
||||||
|
showIcon, |
||||||
|
visible, |
||||||
|
className, |
||||||
|
htmlFor, |
||||||
|
placeholder, |
||||||
|
iconSize, |
||||||
|
inputClassName, |
||||||
|
...rest |
||||||
|
} = props |
||||||
|
|
||||||
|
// ** State
|
||||||
|
const [inputVisibility, setInputVisibility] = useState(visible) |
||||||
|
|
||||||
|
// ** Renders Icon Based On Visibility
|
||||||
|
const renderIcon = () => { |
||||||
|
const size = iconSize ? iconSize : 14 |
||||||
|
|
||||||
|
if (inputVisibility === false) { |
||||||
|
return hideIcon ? hideIcon : <Eye size={size} /> |
||||||
|
} else { |
||||||
|
return showIcon ? showIcon : <EyeOff size={size} /> |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return ( |
||||||
|
<Fragment> |
||||||
|
{label ? <Label for={htmlFor}>{label}</Label> : null} |
||||||
|
<InputGroup |
||||||
|
className={classnames({ |
||||||
|
[className]: className |
||||||
|
})} |
||||||
|
> |
||||||
|
<Input |
||||||
|
type={inputVisibility === false ? 'password' : 'text'} |
||||||
|
placeholder={placeholder ? placeholder : '············'} |
||||||
|
className={classnames({ |
||||||
|
[inputClassName]: inputClassName |
||||||
|
})} |
||||||
|
/*eslint-disable */ |
||||||
|
{...(label && htmlFor |
||||||
|
? { |
||||||
|
id: htmlFor |
||||||
|
} |
||||||
|
: {})} |
||||||
|
{...rest} |
||||||
|
/*eslint-enable */ |
||||||
|
/> |
||||||
|
<InputGroupAddon addonType='append' onClick={() => setInputVisibility(!inputVisibility)}> |
||||||
|
<InputGroupText className='cursor-pointer'>{renderIcon()}</InputGroupText> |
||||||
|
</InputGroupAddon> |
||||||
|
</InputGroup> |
||||||
|
</Fragment> |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
export default InputPasswordToggle |
||||||
|
|
||||||
|
// ** PropTypes
|
||||||
|
InputPasswordToggle.propTypes = { |
||||||
|
hideIcon: PropTypes.node, |
||||||
|
showIcon: PropTypes.node, |
||||||
|
visible: PropTypes.bool, |
||||||
|
className: PropTypes.string, |
||||||
|
placeholder: PropTypes.string, |
||||||
|
iconSize: PropTypes.number, |
||||||
|
inputClassName: PropTypes.string, |
||||||
|
label(props, propName, componentName) { |
||||||
|
// ** If label is defined and htmlFor is undefined throw error
|
||||||
|
if (props[propName] && props['htmlFor'] === 'undefined') { |
||||||
|
throw new Error('htmlFor prop is required when label prop is present') |
||||||
|
} |
||||||
|
}, |
||||||
|
htmlFor(props, propName, componentName) { |
||||||
|
// ** If htmlFor is defined and label is undefined throw error
|
||||||
|
if (props[propName] && props['label'] === 'undefined') { |
||||||
|
throw new Error('label prop is required when htmlFor prop is present') |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// ** Default Props
|
||||||
|
InputPasswordToggle.defaultProps = { |
||||||
|
visible: false |
||||||
|
} |
@ -0,0 +1,205 @@ |
|||||||
|
// ** React Imports
|
||||||
|
import PropTypes from 'prop-types' |
||||||
|
import classnames from 'classnames' |
||||||
|
import { Plus, Minus } from 'react-feather' |
||||||
|
import { useState, useEffect } from 'react' |
||||||
|
import { InputGroup, InputGroupAddon, Input, Button } from 'reactstrap' |
||||||
|
|
||||||
|
// ** Styles
|
||||||
|
import './number-input.scss' |
||||||
|
|
||||||
|
// ** Keycode Vars
|
||||||
|
const KEYCODE_UP = 38 |
||||||
|
const KEYCODE_DOWN = 40 |
||||||
|
|
||||||
|
const NumberInput = props => { |
||||||
|
// ** Props
|
||||||
|
const { |
||||||
|
min, |
||||||
|
max, |
||||||
|
step, |
||||||
|
size, |
||||||
|
wrap, |
||||||
|
value, |
||||||
|
style, |
||||||
|
upIcon, |
||||||
|
disabled, |
||||||
|
readonly, |
||||||
|
onChange, |
||||||
|
downIcon, |
||||||
|
vertical, |
||||||
|
className, |
||||||
|
onDecrement, |
||||||
|
onIncrement, |
||||||
|
inputClassName, |
||||||
|
...rest |
||||||
|
} = props |
||||||
|
|
||||||
|
// ** State
|
||||||
|
const [count, setCount] = useState(value || min) |
||||||
|
|
||||||
|
// ** Handle btn down click
|
||||||
|
const handleDecrement = () => { |
||||||
|
if (!disabled && !readonly) { |
||||||
|
// ** If count is equals or smaller than min then return and do nothing
|
||||||
|
if (!wrap && count <= min) { |
||||||
|
return |
||||||
|
} |
||||||
|
|
||||||
|
// ** Returns the decreased count based on wrap & and min prop
|
||||||
|
const countCondition = () => { |
||||||
|
if (count - step < min) { |
||||||
|
if (wrap) { |
||||||
|
return max |
||||||
|
} else { |
||||||
|
return min |
||||||
|
} |
||||||
|
} else { |
||||||
|
return count - step |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
setCount(countCondition()) |
||||||
|
|
||||||
|
if (onDecrement) { |
||||||
|
onIncrement(count) |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// ** Handle btn up click
|
||||||
|
const handleIncrement = () => { |
||||||
|
if (!disabled && !readonly) { |
||||||
|
// ** If count is equals or larger than min then return and do nothing
|
||||||
|
if (!wrap && count >= max) { |
||||||
|
return |
||||||
|
} |
||||||
|
|
||||||
|
// ** Returns the Increased count based on wrap & and max prop
|
||||||
|
const countCondition = () => { |
||||||
|
if (count + step > max) { |
||||||
|
if (wrap) { |
||||||
|
return min |
||||||
|
} else { |
||||||
|
return max |
||||||
|
} |
||||||
|
} else { |
||||||
|
return count + step |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
setCount(countCondition()) |
||||||
|
|
||||||
|
if (onIncrement) { |
||||||
|
onIncrement(count) |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// ** Handle input change
|
||||||
|
const handleInputChange = e => { |
||||||
|
setCount(Number(e.target.value)) |
||||||
|
} |
||||||
|
|
||||||
|
// ** Handle Arrow Up & Down
|
||||||
|
const handleKeyDown = e => { |
||||||
|
e.preventDefault() |
||||||
|
if (!readonly) { |
||||||
|
if (e.keyCode === KEYCODE_UP) { |
||||||
|
handleIncrement() |
||||||
|
} |
||||||
|
if (e.keyCode === KEYCODE_DOWN) { |
||||||
|
handleDecrement() |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// ** UseEffect based on user passed onChange
|
||||||
|
useEffect(() => { |
||||||
|
if (onChange) { |
||||||
|
onChange(count) |
||||||
|
} |
||||||
|
}, [count]) |
||||||
|
|
||||||
|
return ( |
||||||
|
<InputGroup |
||||||
|
className={classnames('number-input', { |
||||||
|
disabled, |
||||||
|
readonly, |
||||||
|
[className]: className, |
||||||
|
'vertical-number-input': vertical, |
||||||
|
[`vertical-number-input-${size}`]: vertical && size |
||||||
|
})} |
||||||
|
{...(style ? { style } : {})} |
||||||
|
> |
||||||
|
<InputGroupAddon addonType='prepend' onClick={handleDecrement}> |
||||||
|
<Button |
||||||
|
className='btn-icon' |
||||||
|
color='transparent' |
||||||
|
{...(size ? { size } : {})} |
||||||
|
disabled={(!wrap && count <= min) || disabled || readonly} |
||||||
|
> |
||||||
|
{downIcon} |
||||||
|
</Button> |
||||||
|
</InputGroupAddon> |
||||||
|
<Input |
||||||
|
{...rest} |
||||||
|
type='number' |
||||||
|
value={count} |
||||||
|
disabled={disabled} |
||||||
|
readOnly={readonly} |
||||||
|
onKeyDown={handleKeyDown} |
||||||
|
onChange={handleInputChange} |
||||||
|
className={classnames({ |
||||||
|
[inputClassName]: inputClassName |
||||||
|
})} |
||||||
|
{...(size ? { bsSize: size } : {})} |
||||||
|
/> |
||||||
|
<InputGroupAddon addonType='append' onClick={handleIncrement}> |
||||||
|
<Button |
||||||
|
className='btn-icon' |
||||||
|
color='transparent' |
||||||
|
{...(size ? { size } : {})} |
||||||
|
disabled={(!wrap && count >= max) || disabled || readonly} |
||||||
|
> |
||||||
|
{upIcon} |
||||||
|
</Button> |
||||||
|
</InputGroupAddon> |
||||||
|
</InputGroup> |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
export default NumberInput |
||||||
|
|
||||||
|
// ** Default Props
|
||||||
|
NumberInput.defaultProps = { |
||||||
|
min: 1, |
||||||
|
step: 1, |
||||||
|
wrap: false, |
||||||
|
max: Infinity, |
||||||
|
disabled: false, |
||||||
|
readonly: false, |
||||||
|
downIcon: <Minus size={14} />, |
||||||
|
upIcon: <Plus size={14} /> |
||||||
|
} |
||||||
|
|
||||||
|
// ** PropTypes
|
||||||
|
NumberInput.propTypes = { |
||||||
|
wrap: PropTypes.bool, |
||||||
|
min: PropTypes.number, |
||||||
|
max: PropTypes.number, |
||||||
|
step: PropTypes.number, |
||||||
|
value: PropTypes.number, |
||||||
|
style: PropTypes.object, |
||||||
|
vertical: PropTypes.bool, |
||||||
|
disabled: PropTypes.bool, |
||||||
|
readonly: PropTypes.bool, |
||||||
|
onChange: PropTypes.func, |
||||||
|
upIcon: PropTypes.element, |
||||||
|
downIcon: PropTypes.element, |
||||||
|
className: PropTypes.string, |
||||||
|
onDecrement: PropTypes.func, |
||||||
|
onIncrement: PropTypes.func, |
||||||
|
inputClassName: PropTypes.string, |
||||||
|
size: PropTypes.oneOf(['sm', 'lg']) |
||||||
|
} |
@ -0,0 +1,153 @@ |
|||||||
|
// Component: Number Input |
||||||
|
// ======================================================================== |
||||||
|
|
||||||
|
@import '../../scss/base/bootstrap-extended/include'; |
||||||
|
@import '../../scss/base/components/include'; |
||||||
|
|
||||||
|
.number-input { |
||||||
|
border-radius: $border-radius; |
||||||
|
text-align: center; |
||||||
|
border: 1px solid $custom-control-border-color; |
||||||
|
overflow: hidden; |
||||||
|
|
||||||
|
.form-control { |
||||||
|
text-align: center; |
||||||
|
padding: 0 0.25rem; |
||||||
|
border-color: $custom-control-border-color; |
||||||
|
|
||||||
|
::-webkit-outer-spin-button, |
||||||
|
::-webkit-inner-spin-button { |
||||||
|
margin: 0; |
||||||
|
-webkit-appearance: none; |
||||||
|
} |
||||||
|
-moz-appearance: textfield; |
||||||
|
} |
||||||
|
|
||||||
|
&:focus, |
||||||
|
&:active, |
||||||
|
&:focus-within { |
||||||
|
outline: 0; |
||||||
|
box-shadow: none; |
||||||
|
border-color: $primary; |
||||||
|
|
||||||
|
.form-control { |
||||||
|
box-shadow: none; |
||||||
|
border-color: $custom-control-border-color !important; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
&:not(.vertical-number-input) { |
||||||
|
.form-control { |
||||||
|
border-top: 0; |
||||||
|
border-bottom: 0; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
&.disabled, |
||||||
|
&.readonly { |
||||||
|
&:focus, |
||||||
|
&:active, |
||||||
|
&:focus-within { |
||||||
|
outline: 0; |
||||||
|
box-shadow: none; |
||||||
|
border-color: $custom-control-border-color; |
||||||
|
} |
||||||
|
.btn { |
||||||
|
background-color: $input-disabled-bg; |
||||||
|
opacity: 1; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
&.vertical-number-input { |
||||||
|
display: inline-flex; |
||||||
|
flex-direction: column; |
||||||
|
width: auto; |
||||||
|
max-width: 3rem; |
||||||
|
|
||||||
|
.input-group-prepend, |
||||||
|
.input-group-append { |
||||||
|
margin-right: 0; |
||||||
|
margin-left: 0; |
||||||
|
|
||||||
|
.btn { |
||||||
|
width: 100%; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
.input-group-prepend .btn { |
||||||
|
border-bottom-left-radius: 0; |
||||||
|
border-top-right-radius: $btn-border-radius; |
||||||
|
} |
||||||
|
|
||||||
|
.input-group-append .btn { |
||||||
|
border-bottom-left-radius: $btn-border-radius; |
||||||
|
border-top-right-radius: 0; |
||||||
|
} |
||||||
|
|
||||||
|
.form-control { |
||||||
|
border-left: 0; |
||||||
|
border-right: 0; |
||||||
|
width: 100%; |
||||||
|
padding-left: 0.5rem; |
||||||
|
padding-right: 0.5rem; |
||||||
|
font-size: 0.85rem; |
||||||
|
} |
||||||
|
|
||||||
|
&-sm { |
||||||
|
max-width: 2.5rem; |
||||||
|
.form-control { |
||||||
|
padding-left: 0.25rem; |
||||||
|
padding-right: 0.25rem; |
||||||
|
font-size: 0.75rem; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
&-lg { |
||||||
|
max-width: 3.5rem; |
||||||
|
.form-control { |
||||||
|
font-size: 1rem; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
.dark-layout { |
||||||
|
.number-input { |
||||||
|
border-color: $theme-dark-input-border-color; |
||||||
|
|
||||||
|
.input-group-prepend, |
||||||
|
.input-group-append { |
||||||
|
button:not(.disabled) { |
||||||
|
svg { |
||||||
|
stroke: $theme-dark-body-color; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
&:focus, |
||||||
|
&:active, |
||||||
|
&:focus-within { |
||||||
|
border-color: $primary !important; |
||||||
|
|
||||||
|
.form-control { |
||||||
|
border-color: $theme-dark-input-border-color !important; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
&:not(.disabled), |
||||||
|
&:not(.readonly) { |
||||||
|
&:focus, |
||||||
|
&:active, |
||||||
|
&:focus-within { |
||||||
|
border-color: $theme-dark-input-border-color; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
&.disabled, |
||||||
|
&.readonly { |
||||||
|
.btn { |
||||||
|
background-color: $theme-dark-input-disabled-border-color; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,33 @@ |
|||||||
|
// ** Third Party Components
|
||||||
|
import PropTypes from 'prop-types' |
||||||
|
|
||||||
|
const Repeater = props => { |
||||||
|
// ** Props
|
||||||
|
const { count, tag, component, children, ...rest } = props |
||||||
|
|
||||||
|
// ** Custom Tag
|
||||||
|
const Tag = tag |
||||||
|
|
||||||
|
// ** Default Items
|
||||||
|
const items = [] |
||||||
|
|
||||||
|
// ** Loop passed count times and push it in items Array
|
||||||
|
for (let i = 0; i < count; i++) { |
||||||
|
items.push(children(i)) |
||||||
|
} |
||||||
|
|
||||||
|
return <Tag {...rest}>{items}</Tag> |
||||||
|
} |
||||||
|
|
||||||
|
// ** PropTypes
|
||||||
|
Repeater.propTypes = { |
||||||
|
count: PropTypes.number.isRequired, |
||||||
|
tag: PropTypes.string.isRequired |
||||||
|
} |
||||||
|
|
||||||
|
// ** Default Props
|
||||||
|
Repeater.defaultProps = { |
||||||
|
tag: 'div' |
||||||
|
} |
||||||
|
|
||||||
|
export default Repeater |
@ -0,0 +1,75 @@ |
|||||||
|
// ** React Imports
|
||||||
|
import { useState, useEffect } from 'react' |
||||||
|
|
||||||
|
// ** Third Party Components
|
||||||
|
import { Button } from 'reactstrap' |
||||||
|
import classnames from 'classnames' |
||||||
|
|
||||||
|
// ** Styles
|
||||||
|
import './ripple-button.scss' |
||||||
|
|
||||||
|
const RippleButton = ({ className, children, onClick, ...rest }) => { |
||||||
|
// ** States
|
||||||
|
const [mounted, setMounted] = useState(false) |
||||||
|
const [isRippling, setIsRippling] = useState(false) |
||||||
|
const [coords, setCoords] = useState({ x: -1, y: -1 }) |
||||||
|
|
||||||
|
// ** Toggle mounted on mount & unmount
|
||||||
|
useEffect(() => { |
||||||
|
setMounted(true) |
||||||
|
return () => setMounted(false) |
||||||
|
}, []) |
||||||
|
|
||||||
|
// ** Check for coords and set ripple
|
||||||
|
useEffect(() => { |
||||||
|
if (mounted) { |
||||||
|
if (coords.x !== -1 && coords.y !== -1) { |
||||||
|
setIsRippling(true) |
||||||
|
setTimeout(() => setIsRippling(false), 500) |
||||||
|
} else { |
||||||
|
setIsRippling(false) |
||||||
|
} |
||||||
|
} |
||||||
|
}, [coords]) |
||||||
|
|
||||||
|
// ** Reset Coords on ripple end
|
||||||
|
useEffect(() => { |
||||||
|
if (mounted) { |
||||||
|
if (!isRippling) setCoords({ x: -1, y: -1 }) |
||||||
|
} |
||||||
|
}, [isRippling]) |
||||||
|
|
||||||
|
return ( |
||||||
|
<Button |
||||||
|
className={classnames('waves-effect', { |
||||||
|
[className]: className |
||||||
|
})} |
||||||
|
onClick={e => { |
||||||
|
const rect = e.target.getBoundingClientRect() |
||||||
|
setCoords({ x: e.clientX - rect.left, y: e.clientY - rect.top }) |
||||||
|
if (onClick) { |
||||||
|
onClick(e) |
||||||
|
} |
||||||
|
}} |
||||||
|
{...rest} |
||||||
|
> |
||||||
|
{children} |
||||||
|
{isRippling ? ( |
||||||
|
<span |
||||||
|
className='waves-ripple' |
||||||
|
style={{ |
||||||
|
left: coords.x, |
||||||
|
top: coords.y |
||||||
|
}} |
||||||
|
></span> |
||||||
|
) : null} |
||||||
|
</Button> |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
// ** PropTypes
|
||||||
|
RippleButton.propTypes = { |
||||||
|
...Button.propTypes |
||||||
|
} |
||||||
|
|
||||||
|
Button.Ripple = RippleButton |
@ -0,0 +1,36 @@ |
|||||||
|
// Component: Ripple Button |
||||||
|
// ======================================================================== |
||||||
|
|
||||||
|
@import '../../scss/base/bootstrap-extended/include'; |
||||||
|
@import '../../scss/base/components/include'; |
||||||
|
|
||||||
|
.waves-effect { |
||||||
|
position: relative; |
||||||
|
overflow: hidden; |
||||||
|
.waves-ripple { |
||||||
|
position: absolute; |
||||||
|
top: 50%; |
||||||
|
left: 50%; |
||||||
|
transform: translate(-50%, -50%); |
||||||
|
opacity: 0; |
||||||
|
width: 0; |
||||||
|
height: 0; |
||||||
|
border-radius: 50%; |
||||||
|
background: rgba($color: $white, $alpha: 0.5); |
||||||
|
animation: ripple-effect 0.4s ease; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@keyframes ripple-effect { |
||||||
|
0% { |
||||||
|
opacity: 0; |
||||||
|
} |
||||||
|
25% { |
||||||
|
opacity: 1; |
||||||
|
} |
||||||
|
100% { |
||||||
|
width: 200%; |
||||||
|
padding-bottom: 200%; |
||||||
|
opacity: 0; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,89 @@ |
|||||||
|
// ** Third Party Components
|
||||||
|
import { X } from 'react-feather' |
||||||
|
import Proptypes from 'prop-types' |
||||||
|
import classnames from 'classnames' |
||||||
|
import { Modal, ModalHeader, ModalBody } from 'reactstrap' |
||||||
|
|
||||||
|
const Sidebar = props => { |
||||||
|
// ** Props
|
||||||
|
const { |
||||||
|
width, |
||||||
|
open, |
||||||
|
toggleSidebar, |
||||||
|
size, |
||||||
|
bodyClassName, |
||||||
|
contentClassName, |
||||||
|
wrapperClassName, |
||||||
|
headerClassName, |
||||||
|
className, |
||||||
|
title, |
||||||
|
children, |
||||||
|
closeBtn, |
||||||
|
...rest |
||||||
|
} = props |
||||||
|
|
||||||
|
// ** If user passes custom close btn render that else default close btn
|
||||||
|
const renderCloseBtn = closeBtn ? closeBtn : <X className='cursor-pointer' size={15} onClick={toggleSidebar} /> |
||||||
|
|
||||||
|
return ( |
||||||
|
<Modal |
||||||
|
isOpen={open} |
||||||
|
toggle={toggleSidebar} |
||||||
|
contentClassName={classnames({ |
||||||
|
[contentClassName]: contentClassName |
||||||
|
})} |
||||||
|
modalClassName={classnames('modal-slide-in', { |
||||||
|
[wrapperClassName]: wrapperClassName |
||||||
|
})} |
||||||
|
className={classnames({ |
||||||
|
[className]: className, |
||||||
|
'sidebar-lg': size === 'lg', |
||||||
|
'sidebar-sm': size === 'sm' |
||||||
|
})} |
||||||
|
/*eslint-disable */ |
||||||
|
{...(width !== undefined |
||||||
|
? { |
||||||
|
style: { width: String(width) + 'px' } |
||||||
|
} |
||||||
|
: {})} |
||||||
|
/*eslint-enable */ |
||||||
|
{...rest} |
||||||
|
> |
||||||
|
<ModalHeader |
||||||
|
className={classnames({ |
||||||
|
[headerClassName]: headerClassName |
||||||
|
})} |
||||||
|
toggle={toggleSidebar} |
||||||
|
close={renderCloseBtn} |
||||||
|
tag='div' |
||||||
|
> |
||||||
|
<h5 className='modal-title'> |
||||||
|
<span className='align-middle'>{title}</span> |
||||||
|
</h5> |
||||||
|
</ModalHeader> |
||||||
|
<ModalBody |
||||||
|
className={classnames('flex-grow-1', { |
||||||
|
[bodyClassName]: bodyClassName |
||||||
|
})} |
||||||
|
> |
||||||
|
{children} |
||||||
|
</ModalBody> |
||||||
|
</Modal> |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
export default Sidebar |
||||||
|
|
||||||
|
// ** PropTypes
|
||||||
|
Sidebar.propTypes = { |
||||||
|
title: Proptypes.string.isRequired, |
||||||
|
open: Proptypes.bool.isRequired, |
||||||
|
toggleSidebar: Proptypes.func.isRequired, |
||||||
|
size: Proptypes.oneOf(['sm', 'lg']), |
||||||
|
className: Proptypes.string, |
||||||
|
bodyClassName: Proptypes.string, |
||||||
|
contentClassName: Proptypes.string, |
||||||
|
wrapperClassName: Proptypes.string, |
||||||
|
children: Proptypes.any.isRequired, |
||||||
|
width: Proptypes.oneOfType([Proptypes.number, Proptypes.string]) |
||||||
|
} |
@ -0,0 +1,17 @@ |
|||||||
|
// ** Logo
|
||||||
|
import logo from '@src/assets/images/logo/logo.png' |
||||||
|
|
||||||
|
const SpinnerComponent = () => { |
||||||
|
return ( |
||||||
|
<div className='fallback-spinner vh-100'> |
||||||
|
<img className='fallback-logo' src={logo} alt='logo' /> |
||||||
|
<div className='loading'> |
||||||
|
<div className='effect-1 effects'></div> |
||||||
|
<div className='effect-2 effects'></div> |
||||||
|
<div className='effect-3 effects'></div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
export default SpinnerComponent |
@ -0,0 +1,13 @@ |
|||||||
|
const ComponentSpinner = () => { |
||||||
|
return ( |
||||||
|
<div className='fallback-spinner'> |
||||||
|
<div className='loading component-loader'> |
||||||
|
<div className='effect-1 effects'></div> |
||||||
|
<div className='effect-2 effects'></div> |
||||||
|
<div className='effect-3 effects'></div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
export default ComponentSpinner |
@ -0,0 +1,52 @@ |
|||||||
|
// ** Third Party Components
|
||||||
|
import Proptypes from 'prop-types' |
||||||
|
import classnames from 'classnames' |
||||||
|
import Chart from 'react-apexcharts' |
||||||
|
import { Card, CardBody } from 'reactstrap' |
||||||
|
|
||||||
|
const StatisticsCards = props => { |
||||||
|
// ** Props
|
||||||
|
const { className, hideChart, iconRight, iconBg, icon, stat, statTitle, options, series, type, height } = props |
||||||
|
|
||||||
|
return ( |
||||||
|
<Card> |
||||||
|
<CardBody |
||||||
|
className={classnames('stats-card-body d-flex pt-2', { |
||||||
|
[className]: className, |
||||||
|
'flex-column align-items-start': !iconRight && !hideChart, |
||||||
|
'justify-content-between flex-row-reverse align-items-center': iconRight, |
||||||
|
'justify-content-center flex-column text-center': hideChart && !iconRight, |
||||||
|
'pb-0': !hideChart, |
||||||
|
'pb-2': hideChart |
||||||
|
})} |
||||||
|
> |
||||||
|
<div className='icon-section'> |
||||||
|
<div className={`avatar avatar-stats p-50 m-0 ${iconBg ? `bg-light-${iconBg}` : 'bg-light-primary'}`}> |
||||||
|
<div className='avatar-content'>{icon}</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
<div className='title-section'> |
||||||
|
<h2 className='font-weight-bold mt-1 mb-25'>{stat}</h2> |
||||||
|
<p className='mb-0'>{statTitle}</p> |
||||||
|
</div> |
||||||
|
</CardBody> |
||||||
|
{!hideChart && <Chart options={options} series={series} type={type} height={height ? height : 100} />} |
||||||
|
</Card> |
||||||
|
) |
||||||
|
} |
||||||
|
export default StatisticsCards |
||||||
|
|
||||||
|
// ** PropTypes
|
||||||
|
StatisticsCards.propTypes = { |
||||||
|
className: Proptypes.string, |
||||||
|
hideChart: Proptypes.bool, |
||||||
|
iconRight: Proptypes.bool, |
||||||
|
iconBg: Proptypes.string, |
||||||
|
icon: Proptypes.node.isRequired, |
||||||
|
stat: Proptypes.string.isRequired, |
||||||
|
statTitle: Proptypes.string.isRequired, |
||||||
|
options: Proptypes.object, |
||||||
|
series: Proptypes.array, |
||||||
|
type: Proptypes.string, |
||||||
|
height: Proptypes.string |
||||||
|
} |
@ -0,0 +1,76 @@ |
|||||||
|
// ** Third Party Components
|
||||||
|
import Proptypes from 'prop-types' |
||||||
|
import classnames from 'classnames' |
||||||
|
|
||||||
|
const Timeline = props => { |
||||||
|
// ** Props
|
||||||
|
const { data, tag, className } = props |
||||||
|
|
||||||
|
// ** Custom Tagg
|
||||||
|
const Tag = tag ? tag : 'ul' |
||||||
|
|
||||||
|
return ( |
||||||
|
<Tag |
||||||
|
className={classnames('timeline', { |
||||||
|
[className]: className |
||||||
|
})} |
||||||
|
> |
||||||
|
{data.map((item, i) => { |
||||||
|
const ItemTag = item.tag ? item.tag : 'li' |
||||||
|
|
||||||
|
return ( |
||||||
|
<ItemTag |
||||||
|
key={i} |
||||||
|
className={classnames('timeline-item', { |
||||||
|
[item.className]: className |
||||||
|
})} |
||||||
|
> |
||||||
|
<span |
||||||
|
className={classnames('timeline-point', { |
||||||
|
[`timeline-point-${item.color}`]: item.color, |
||||||
|
'timeline-point-indicator': !item.icon |
||||||
|
})} |
||||||
|
> |
||||||
|
{item.icon ? item.icon : null} |
||||||
|
</span> |
||||||
|
<div className='timeline-event'> |
||||||
|
<div |
||||||
|
className={classnames('d-flex justify-content-between flex-sm-row flex-column', { |
||||||
|
'mb-sm-0 mb-1': item.meta |
||||||
|
})} |
||||||
|
> |
||||||
|
<h6>{item.title}</h6> |
||||||
|
{item.meta ? ( |
||||||
|
<span |
||||||
|
className={classnames('timeline-event-time', { |
||||||
|
[item.metaClassName]: item.metaClassName |
||||||
|
})} |
||||||
|
> |
||||||
|
{item.meta} |
||||||
|
</span> |
||||||
|
) : null} |
||||||
|
</div> |
||||||
|
<p |
||||||
|
className={classnames({ |
||||||
|
'mb-0': i === data.length - 1 && !item.customContent |
||||||
|
})} |
||||||
|
> |
||||||
|
{item.content} |
||||||
|
</p> |
||||||
|
{item.customContent ? item.customContent : null} |
||||||
|
</div> |
||||||
|
</ItemTag> |
||||||
|
) |
||||||
|
})} |
||||||
|
</Tag> |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
export default Timeline |
||||||
|
|
||||||
|
// ** PropTypes
|
||||||
|
Timeline.propTypes = { |
||||||
|
data: Proptypes.array.isRequired, |
||||||
|
className: Proptypes.string, |
||||||
|
tag: Proptypes.string |
||||||
|
} |
@ -0,0 +1,45 @@ |
|||||||
|
// ** Third Party Components
|
||||||
|
import { Fragment } from 'react' |
||||||
|
import Proptypes from 'prop-types' |
||||||
|
import classnames from 'classnames' |
||||||
|
import { Spinner } from 'reactstrap' |
||||||
|
|
||||||
|
import './ui-loader.scss' |
||||||
|
|
||||||
|
const UILoader = props => { |
||||||
|
const { children, blocking, loader, className, tag, overlayColor } = props |
||||||
|
|
||||||
|
const Tag = tag |
||||||
|
|
||||||
|
return ( |
||||||
|
<Tag className={classnames('ui-loader', { [className]: className, show: blocking })}> |
||||||
|
{children} |
||||||
|
{blocking ? ( |
||||||
|
<Fragment> |
||||||
|
<div |
||||||
|
className='overlay' /*eslint-disable */ |
||||||
|
{...(blocking && overlayColor ? { style: { backgroundColor: overlayColor } } : {})} |
||||||
|
/*eslint-enable */ |
||||||
|
></div> |
||||||
|
<div className='loader'>{loader}</div> |
||||||
|
</Fragment> |
||||||
|
) : null} |
||||||
|
</Tag> |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
export default UILoader |
||||||
|
|
||||||
|
UILoader.defaultProps = { |
||||||
|
tag: 'div', |
||||||
|
blocking: false, |
||||||
|
loader: <Spinner color='primary' /> |
||||||
|
} |
||||||
|
|
||||||
|
UILoader.propTypes = { |
||||||
|
tag: Proptypes.string, |
||||||
|
loader: Proptypes.any, |
||||||
|
className: Proptypes.string, |
||||||
|
overlayColor: Proptypes.string, |
||||||
|
blocking: Proptypes.bool.isRequired |
||||||
|
} |
@ -0,0 +1,35 @@ |
|||||||
|
// Component: UI Loader |
||||||
|
// ======================================================================== |
||||||
|
|
||||||
|
@import '../../scss/base/bootstrap-extended/include'; |
||||||
|
@import '../../scss/base/components/include'; |
||||||
|
|
||||||
|
.ui-loader { |
||||||
|
position: relative; |
||||||
|
|
||||||
|
&.show { |
||||||
|
// background-color: rgba($color: $black, $alpha: 0.3); |
||||||
|
.overlay { |
||||||
|
content: ''; |
||||||
|
position: absolute; |
||||||
|
width: 100%; |
||||||
|
height: 100%; |
||||||
|
top: 0; |
||||||
|
background-color: rgba($color: $black, $alpha: 0.3); |
||||||
|
} |
||||||
|
|
||||||
|
> :first-child, |
||||||
|
code { |
||||||
|
background-color: initial; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
.loader { |
||||||
|
position: absolute; |
||||||
|
top: 50%; |
||||||
|
left: 50%; |
||||||
|
height: 50%; |
||||||
|
margin-top: -1rem; |
||||||
|
margin-left: -1rem; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,104 @@ |
|||||||
|
// ** Area Chart Common Options
|
||||||
|
export const areaChartOptions = { |
||||||
|
chart: { |
||||||
|
toolbar: { |
||||||
|
show: false |
||||||
|
}, |
||||||
|
sparkline: { |
||||||
|
enabled: true |
||||||
|
} |
||||||
|
}, |
||||||
|
grid: { |
||||||
|
show: false |
||||||
|
}, |
||||||
|
colors: ['#7367F0'], |
||||||
|
dataLabels: { |
||||||
|
enabled: false |
||||||
|
}, |
||||||
|
stroke: { |
||||||
|
curve: 'smooth', |
||||||
|
width: 2.5 |
||||||
|
}, |
||||||
|
fill: { |
||||||
|
type: 'gradient', |
||||||
|
gradient: { |
||||||
|
shadeIntensity: 0.9, |
||||||
|
opacityFrom: 0.7, |
||||||
|
opacityTo: 0.5, |
||||||
|
stops: [0, 80, 100] |
||||||
|
} |
||||||
|
}, |
||||||
|
xaxis: { |
||||||
|
labels: { |
||||||
|
show: false |
||||||
|
}, |
||||||
|
axisBorder: { |
||||||
|
show: false |
||||||
|
} |
||||||
|
}, |
||||||
|
yaxis: { |
||||||
|
labels: { |
||||||
|
show: false |
||||||
|
} |
||||||
|
}, |
||||||
|
tooltip: { |
||||||
|
x: { show: false } |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// ** Line Chart Common Options
|
||||||
|
export const lineChartOptions = { |
||||||
|
chart: { |
||||||
|
toolbar: { |
||||||
|
show: false |
||||||
|
}, |
||||||
|
sparkline: { |
||||||
|
enabled: true |
||||||
|
}, |
||||||
|
dropShadow: { |
||||||
|
enabled: true, |
||||||
|
top: 5, |
||||||
|
left: 0, |
||||||
|
blur: 4, |
||||||
|
opacity: 0.1 |
||||||
|
} |
||||||
|
}, |
||||||
|
grid: { |
||||||
|
show: false |
||||||
|
}, |
||||||
|
colors: ['#7367F0'], |
||||||
|
dataLabels: { |
||||||
|
enabled: false |
||||||
|
}, |
||||||
|
stroke: { |
||||||
|
curve: 'smooth', |
||||||
|
width: 5 |
||||||
|
}, |
||||||
|
fill: { |
||||||
|
type: 'gradient', |
||||||
|
gradient: { |
||||||
|
shadeIntensity: 1, |
||||||
|
gradientToColors: ['#A9A2F6'], |
||||||
|
opacityFrom: 1, |
||||||
|
opacityTo: 1, |
||||||
|
stops: [0, 100, 100, 100] |
||||||
|
} |
||||||
|
}, |
||||||
|
|
||||||
|
xaxis: { |
||||||
|
labels: { |
||||||
|
show: false |
||||||
|
}, |
||||||
|
axisBorder: { |
||||||
|
show: false |
||||||
|
} |
||||||
|
}, |
||||||
|
yaxis: { |
||||||
|
labels: { |
||||||
|
show: false |
||||||
|
} |
||||||
|
}, |
||||||
|
tooltip: { |
||||||
|
x: { show: false } |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,32 @@ |
|||||||
|
// ** Third Party Components
|
||||||
|
import PropTypes from 'prop-types' |
||||||
|
import { Card, CardBody } from 'reactstrap' |
||||||
|
|
||||||
|
const StatsHorizontal = ({ icon, color, stats, statTitle, className, ...rest }) => { |
||||||
|
return ( |
||||||
|
<Card> |
||||||
|
<CardBody className={className}> |
||||||
|
<div className='d-flex justify-content-between align-items-center'> |
||||||
|
<div> |
||||||
|
<h2 className='font-weight-bolder mb-0'>{stats}</h2> |
||||||
|
<p className='card-text'>{statTitle}</p> |
||||||
|
</div> |
||||||
|
<div className={`avatar avatar-stats p-50 m-0 ${color ? `bg-light-${color}` : 'bg-light-primary'}`}> |
||||||
|
<div className='avatar-content'>{icon}</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</CardBody> |
||||||
|
</Card> |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
export default StatsHorizontal |
||||||
|
|
||||||
|
// ** PropTypes
|
||||||
|
StatsHorizontal.propTypes = { |
||||||
|
icon: PropTypes.element.isRequired, |
||||||
|
color: PropTypes.string.isRequired, |
||||||
|
stats: PropTypes.string.isRequired, |
||||||
|
statTitle: PropTypes.string.isRequired, |
||||||
|
className: PropTypes.string |
||||||
|
} |
@ -0,0 +1,28 @@ |
|||||||
|
// ** Third Party Components
|
||||||
|
import PropTypes from 'prop-types' |
||||||
|
import { Card, CardBody } from 'reactstrap' |
||||||
|
|
||||||
|
const StatsVertical = ({ icon, color, stats, statTitle, className, ...rest }) => { |
||||||
|
return ( |
||||||
|
<Card className='text-center'> |
||||||
|
<CardBody className={className}> |
||||||
|
<div className={`avatar p-50 m-0 mb-1 ${color ? `bg-light-${color}` : 'bg-light-primary'}`}> |
||||||
|
<div className='avatar-content'>{icon}</div> |
||||||
|
</div> |
||||||
|
<h2 className='font-weight-bolder'>{stats}</h2> |
||||||
|
<p className='card-text line-ellipsis'>{statTitle}</p> |
||||||
|
</CardBody> |
||||||
|
</Card> |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
export default StatsVertical |
||||||
|
|
||||||
|
// ** PropTypes
|
||||||
|
StatsVertical.propTypes = { |
||||||
|
icon: PropTypes.element.isRequired, |
||||||
|
color: PropTypes.string.isRequired, |
||||||
|
stats: PropTypes.string.isRequired, |
||||||
|
statTitle: PropTypes.string.isRequired, |
||||||
|
className: PropTypes.string |
||||||
|
} |
@ -0,0 +1,51 @@ |
|||||||
|
// ** Custom Components
|
||||||
|
import Avatar from '@components/avatar' |
||||||
|
|
||||||
|
// ** Third Party Components
|
||||||
|
import PropTypes from 'prop-types' |
||||||
|
import classnames from 'classnames' |
||||||
|
import Chart from 'react-apexcharts' |
||||||
|
import { Card, CardBody } from 'reactstrap' |
||||||
|
|
||||||
|
// ** Default Options
|
||||||
|
import { areaChartOptions } from './ChartOptions' |
||||||
|
|
||||||
|
const StatsWithAreaChart = props => { |
||||||
|
// ** Props
|
||||||
|
const { icon, color, stats, statTitle, series, options, type, height, className, ...rest } = props |
||||||
|
return ( |
||||||
|
<Card {...rest}> |
||||||
|
<CardBody |
||||||
|
className={classnames('pb-0', { |
||||||
|
[className]: className |
||||||
|
})} |
||||||
|
> |
||||||
|
<Avatar className='avatar-stats p-50 m-0' color={`light-${color}`} icon={icon} /> |
||||||
|
<h2 className='font-weight-bolder mt-1'>{stats}</h2> |
||||||
|
<p className='card-text'>{statTitle}</p> |
||||||
|
</CardBody> |
||||||
|
<Chart options={options} series={series} type={type} height={height ? height : 100} /> |
||||||
|
</Card> |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
export default StatsWithAreaChart |
||||||
|
|
||||||
|
// ** PropTypes
|
||||||
|
StatsWithAreaChart.propTypes = { |
||||||
|
icon: PropTypes.element.isRequired, |
||||||
|
color: PropTypes.string.isRequired, |
||||||
|
stats: PropTypes.string.isRequired, |
||||||
|
statTitle: PropTypes.string.isRequired, |
||||||
|
options: PropTypes.object, |
||||||
|
series: PropTypes.array.isRequired, |
||||||
|
type: PropTypes.string, |
||||||
|
height: PropTypes.string, |
||||||
|
className: PropTypes.string |
||||||
|
} |
||||||
|
|
||||||
|
// ** Default Props
|
||||||
|
StatsWithAreaChart.defaultProps = { |
||||||
|
options: areaChartOptions, |
||||||
|
color: 'primary' |
||||||
|
} |
@ -0,0 +1,45 @@ |
|||||||
|
// ** Custom Components
|
||||||
|
import Avatar from '@components/avatar' |
||||||
|
|
||||||
|
// ** Third Party Components
|
||||||
|
import PropTypes from 'prop-types' |
||||||
|
import Chart from 'react-apexcharts' |
||||||
|
import { Card, CardHeader, CardText } from 'reactstrap' |
||||||
|
|
||||||
|
// ** Default Options
|
||||||
|
import { lineChartOptions } from './ChartOptions' |
||||||
|
|
||||||
|
const StatsWithLineChart = ({ icon, color, stats, statTitle, series, options, type, height, ...rest }) => { |
||||||
|
return ( |
||||||
|
<Card {...rest}> |
||||||
|
<CardHeader className='align-items-start pb-0'> |
||||||
|
<div> |
||||||
|
<h2 className='font-weight-bolder'>{stats}</h2> |
||||||
|
<CardText>{statTitle}</CardText> |
||||||
|
</div> |
||||||
|
<Avatar className='avatar-stats p-50 m-0' color={`light-${color}`} icon={icon} /> |
||||||
|
</CardHeader> |
||||||
|
<Chart options={options} series={series} type={type} height={height ? height : 100} /> |
||||||
|
</Card> |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
export default StatsWithLineChart |
||||||
|
|
||||||
|
// ** PropTypes
|
||||||
|
StatsWithLineChart.propTypes = { |
||||||
|
icon: PropTypes.element.isRequired, |
||||||
|
color: PropTypes.string.isRequired, |
||||||
|
stats: PropTypes.string.isRequired, |
||||||
|
statTitle: PropTypes.string.isRequired, |
||||||
|
options: PropTypes.object, |
||||||
|
series: PropTypes.array.isRequired, |
||||||
|
type: PropTypes.string, |
||||||
|
height: PropTypes.string |
||||||
|
} |
||||||
|
|
||||||
|
// ** Default Props
|
||||||
|
StatsWithLineChart.defaultProps = { |
||||||
|
options: lineChartOptions, |
||||||
|
color: 'primary' |
||||||
|
} |
@ -0,0 +1,35 @@ |
|||||||
|
// ** Third Party Components
|
||||||
|
import PropTypes from 'prop-types' |
||||||
|
import Chart from 'react-apexcharts' |
||||||
|
import { Card, CardBody } from 'reactstrap' |
||||||
|
|
||||||
|
const TinyChartStats = props => { |
||||||
|
// ** Props
|
||||||
|
const { title, stats, options, series, type, height } = props |
||||||
|
|
||||||
|
return ( |
||||||
|
<Card className='card-tiny-line-stats'> |
||||||
|
<CardBody className='pb-50'> |
||||||
|
<h6>{title}</h6> |
||||||
|
<h2 className='font-weight-bolder mb-1'>{stats}</h2> |
||||||
|
<Chart options={options} series={series} type={type} height={height} /> |
||||||
|
</CardBody> |
||||||
|
</Card> |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
export default TinyChartStats |
||||||
|
|
||||||
|
// ** PropTypes
|
||||||
|
TinyChartStats.propTypes = { |
||||||
|
title: PropTypes.string.isRequired, |
||||||
|
stats: PropTypes.string.isRequired, |
||||||
|
options: PropTypes.object.isRequired, |
||||||
|
series: PropTypes.array.isRequired, |
||||||
|
type: PropTypes.string.isRequired |
||||||
|
} |
||||||
|
|
||||||
|
// ** Default Props
|
||||||
|
TinyChartStats.defaultProps = { |
||||||
|
height: 100 |
||||||
|
} |
@ -0,0 +1,121 @@ |
|||||||
|
// ** React Imports
|
||||||
|
import { useEffect, useState, Fragment, forwardRef } from 'react' |
||||||
|
|
||||||
|
// ** Third Party Components
|
||||||
|
import Stepper from 'bs-stepper' |
||||||
|
import classnames from 'classnames' |
||||||
|
import { PropTypes } from 'prop-types' |
||||||
|
import { ChevronRight } from 'react-feather' |
||||||
|
|
||||||
|
// ** Styles
|
||||||
|
import 'bs-stepper/dist/css/bs-stepper.min.css' |
||||||
|
import '../../../@core/scss/base/plugins/forms/form-wizard.scss' |
||||||
|
|
||||||
|
const Wizard = forwardRef((props, ref) => { |
||||||
|
// ** Props
|
||||||
|
const { type, className, steps, separator, options, instance } = props |
||||||
|
|
||||||
|
// ** State
|
||||||
|
const [activeIndex, setActiveIndex] = useState(0) |
||||||
|
|
||||||
|
// ** Vars
|
||||||
|
let stepper = null |
||||||
|
|
||||||
|
// ** Step change listener on mount
|
||||||
|
useEffect(() => { |
||||||
|
stepper = new Stepper(ref.current, options) |
||||||
|
|
||||||
|
ref.current.addEventListener('shown.bs-stepper', function (event) { |
||||||
|
setActiveIndex(event.detail.indexStep) |
||||||
|
}) |
||||||
|
|
||||||
|
if (instance) { |
||||||
|
instance(stepper) |
||||||
|
} |
||||||
|
}, []) |
||||||
|
|
||||||
|
// ** Renders Wizard Header
|
||||||
|
const renderHeader = () => { |
||||||
|
return steps.map((step, index) => { |
||||||
|
return ( |
||||||
|
<Fragment key={step.id}> |
||||||
|
{index !== 0 && index !== steps.length ? <div className='line'>{separator}</div> : null} |
||||||
|
<div |
||||||
|
className={classnames('step', { |
||||||
|
crossed: activeIndex > index, |
||||||
|
active: index === activeIndex |
||||||
|
})} |
||||||
|
data-target={`#${step.id}`} |
||||||
|
> |
||||||
|
<button type='button' className='step-trigger'> |
||||||
|
<span className='bs-stepper-box'>{step.icon ? step.icon : index + 1}</span> |
||||||
|
<span className='bs-stepper-label'> |
||||||
|
<span className='bs-stepper-title'>{step.title}</span> |
||||||
|
{step.subtitle ? <span className='bs-stepper-subtitle'>{step.subtitle}</span> : null} |
||||||
|
</span> |
||||||
|
</button> |
||||||
|
</div> |
||||||
|
</Fragment> |
||||||
|
) |
||||||
|
}) |
||||||
|
} |
||||||
|
|
||||||
|
// ** Renders Wizard Content
|
||||||
|
const renderContent = () => { |
||||||
|
return steps.map((step, index) => { |
||||||
|
return ( |
||||||
|
<div |
||||||
|
className={classnames('content', { |
||||||
|
'active dstepper-block': activeIndex === index |
||||||
|
})} |
||||||
|
id={step.id} |
||||||
|
key={step.id} |
||||||
|
> |
||||||
|
{step.content} |
||||||
|
</div> |
||||||
|
) |
||||||
|
}) |
||||||
|
} |
||||||
|
|
||||||
|
return ( |
||||||
|
<div |
||||||
|
ref={ref} |
||||||
|
className={classnames('bs-stepper', { |
||||||
|
[className]: className, |
||||||
|
vertical: type === 'vertical', |
||||||
|
'vertical wizard-modern': type === 'modern-vertical', |
||||||
|
'wizard-modern': type === 'modern-horizontal' |
||||||
|
})} |
||||||
|
> |
||||||
|
<div className='bs-stepper-header'>{renderHeader()}</div> |
||||||
|
<div className='bs-stepper-content'>{renderContent()}</div> |
||||||
|
</div> |
||||||
|
) |
||||||
|
}) |
||||||
|
|
||||||
|
export default Wizard |
||||||
|
|
||||||
|
// ** Default Props
|
||||||
|
Wizard.defaultProps = { |
||||||
|
type: 'horizontal', |
||||||
|
separator: <ChevronRight size={17} />, |
||||||
|
options: {} |
||||||
|
} |
||||||
|
|
||||||
|
// ** PropTypes
|
||||||
|
Wizard.propTypes = { |
||||||
|
type: PropTypes.string, |
||||||
|
instance: PropTypes.func, |
||||||
|
options: PropTypes.object, |
||||||
|
className: PropTypes.string, |
||||||
|
separator: PropTypes.element, |
||||||
|
steps: PropTypes.arrayOf( |
||||||
|
PropTypes.shape({ |
||||||
|
id: PropTypes.string.isRequired, |
||||||
|
title: PropTypes.string.isRequired, |
||||||
|
subtitle: PropTypes.string, |
||||||
|
icon: PropTypes.any, |
||||||
|
content: PropTypes.any.isRequired |
||||||
|
}) |
||||||
|
).isRequired |
||||||
|
} |
@ -0,0 +1,35 @@ |
|||||||
|
// ** React Imports
|
||||||
|
import { useEffect, useState } from 'react' |
||||||
|
|
||||||
|
// ** Custom Hooks
|
||||||
|
import { useSkin } from '@hooks/useSkin' |
||||||
|
|
||||||
|
const BlankLayout = ({ children, ...rest }) => { |
||||||
|
// ** Hooks
|
||||||
|
const [skin, setSkin] = useSkin() |
||||||
|
|
||||||
|
// ** States
|
||||||
|
const [isMounted, setIsMounted] = useState(false) |
||||||
|
|
||||||
|
//** ComponentDidMount
|
||||||
|
useEffect(() => { |
||||||
|
setIsMounted(true) |
||||||
|
return () => setIsMounted(false) |
||||||
|
}, []) |
||||||
|
|
||||||
|
if (!isMounted) { |
||||||
|
return null |
||||||
|
} |
||||||
|
|
||||||
|
return ( |
||||||
|
<div className='blank-page'> |
||||||
|
<div className='app-content content'> |
||||||
|
<div className='content-wrapper'> |
||||||
|
<div className='content-body'>{children}</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
export default BlankLayout |
@ -0,0 +1,122 @@ |
|||||||
|
// ** React Imports
|
||||||
|
import { useState, useEffect } from 'react'; |
||||||
|
import { useLocation } from 'react-router-dom'; |
||||||
|
|
||||||
|
// ** Store & Actions
|
||||||
|
import { useSelector, useDispatch } from 'react-redux'; |
||||||
|
import { |
||||||
|
handleMenuCollapsed, |
||||||
|
handleContentWidth, |
||||||
|
handleMenuHidden |
||||||
|
} from '@store/actions/layout'; |
||||||
|
|
||||||
|
// ** Third Party Components
|
||||||
|
import classnames from 'classnames'; |
||||||
|
import { ArrowUp } from 'react-feather'; |
||||||
|
import ScrollToTop from 'react-scroll-up'; |
||||||
|
import { Navbar, Button } from 'reactstrap'; |
||||||
|
|
||||||
|
// ** Configs
|
||||||
|
import themeConfig from '@configs/themeConfig'; |
||||||
|
|
||||||
|
// ** Custom Components
|
||||||
|
import Customizer from '@components/customizer'; |
||||||
|
import FooterComponent from './components/footer'; |
||||||
|
import NavbarComponent from './components/navbar'; |
||||||
|
import SidebarComponent from './components/menu/vertical-menu'; |
||||||
|
|
||||||
|
// ** Custom Hooks
|
||||||
|
import { useRTL } from '@hooks/useRTL'; |
||||||
|
import { useSkin } from '@hooks/useSkin'; |
||||||
|
import { useNavbarType } from '@hooks/useNavbarType'; |
||||||
|
import { useFooterType } from '@hooks/useFooterType'; |
||||||
|
import { useNavbarColor } from '@hooks/useNavbarColor'; |
||||||
|
|
||||||
|
// ** Styles
|
||||||
|
import '@styles/base/core/menu/menu-types/vertical-menu.scss'; |
||||||
|
import '@styles/base/core/menu/menu-types/vertical-overlay-menu.scss'; |
||||||
|
|
||||||
|
const HeaderLayout = props => { |
||||||
|
// ** Props
|
||||||
|
const { children, navbar, footer, menu, routerProps, currentActiveItem } = |
||||||
|
props; |
||||||
|
|
||||||
|
// ** Hooks
|
||||||
|
const [skin, setSkin] = useSkin(); |
||||||
|
const [navbarColor, setNavbarColor] = useNavbarColor(); |
||||||
|
|
||||||
|
// ** States
|
||||||
|
const [isMounted, setIsMounted] = useState(false); |
||||||
|
const [menuVisibility, setMenuVisibility] = useState(false); |
||||||
|
const [windowWidth, setWindowWidth] = useState(window.innerWidth); |
||||||
|
|
||||||
|
// ** Store Vars
|
||||||
|
const layoutStore = useSelector(state => state.layout); |
||||||
|
|
||||||
|
// ** Update Window Width
|
||||||
|
const handleWindowWidth = () => { |
||||||
|
setWindowWidth(window.innerWidth); |
||||||
|
}; |
||||||
|
|
||||||
|
// ** Vars
|
||||||
|
const location = useLocation(); |
||||||
|
|
||||||
|
//** This function will detect the Route Change and will hide the menu on menu item click
|
||||||
|
useEffect(() => { |
||||||
|
if (menuVisibility && windowWidth < 1200) { |
||||||
|
setMenuVisibility(false); |
||||||
|
} |
||||||
|
}, [location]); |
||||||
|
|
||||||
|
//** Sets Window Size & Layout Props
|
||||||
|
useEffect(() => { |
||||||
|
if (window !== undefined) { |
||||||
|
window.addEventListener('resize', handleWindowWidth); |
||||||
|
} |
||||||
|
}, [windowWidth]); |
||||||
|
|
||||||
|
//** ComponentDidMount
|
||||||
|
useEffect(() => { |
||||||
|
setIsMounted(true); |
||||||
|
return () => setIsMounted(false); |
||||||
|
}, []); |
||||||
|
|
||||||
|
const bgColorCondition = |
||||||
|
navbarColor !== '' && navbarColor !== 'light' && navbarColor !== 'white'; |
||||||
|
|
||||||
|
if (!isMounted) { |
||||||
|
return null; |
||||||
|
} |
||||||
|
return ( |
||||||
|
<div className='blank-page'> |
||||||
|
<div className='app-content content'> |
||||||
|
<div className='content-wrapper'> |
||||||
|
<Navbar |
||||||
|
expand='lg' |
||||||
|
light={skin !== 'dark'} |
||||||
|
dark={skin === 'dark' || bgColorCondition} |
||||||
|
color={bgColorCondition ? navbarColor : undefined} |
||||||
|
className={classnames( |
||||||
|
'header-navbar navbar align-items-center floating-nav2 navbar-shadow' |
||||||
|
)} |
||||||
|
> |
||||||
|
<div className='navbar-container d-flex content'> |
||||||
|
{navbar ? ( |
||||||
|
navbar |
||||||
|
) : ( |
||||||
|
<NavbarComponent |
||||||
|
setMenuVisibility={setMenuVisibility} |
||||||
|
skin={skin} |
||||||
|
setSkin={setSkin} |
||||||
|
/> |
||||||
|
)} |
||||||
|
</div> |
||||||
|
</Navbar> |
||||||
|
<div className='content-body'>{children}</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
); |
||||||
|
}; |
||||||
|
|
||||||
|
export default HeaderLayout; |
@ -0,0 +1,202 @@ |
|||||||
|
// ** React Imports
|
||||||
|
import { useState, useEffect } from 'react' |
||||||
|
import { Link } from 'react-router-dom' |
||||||
|
|
||||||
|
// ** Store & Actions
|
||||||
|
import { useSelector, useDispatch } from 'react-redux' |
||||||
|
import { handleMenuHidden, handleContentWidth } from '@store/actions/layout' |
||||||
|
|
||||||
|
// ** Third Party Components
|
||||||
|
import classnames from 'classnames' |
||||||
|
import { ArrowUp } from 'react-feather' |
||||||
|
import ScrollToTop from 'react-scroll-up' |
||||||
|
import { Navbar, NavItem, Button } from 'reactstrap' |
||||||
|
|
||||||
|
// ** Configs
|
||||||
|
import themeConfig from '@configs/themeConfig' |
||||||
|
|
||||||
|
// ** Custom Components
|
||||||
|
import Customizer from '@components/customizer' |
||||||
|
import NavbarComponent from './components/navbar' |
||||||
|
import FooterComponent from './components/footer' |
||||||
|
import MenuComponent from './components/menu/horizontal-menu' |
||||||
|
|
||||||
|
// ** Custom Hooks
|
||||||
|
import { useRTL } from '@hooks/useRTL' |
||||||
|
import { useSkin } from '@hooks/useSkin' |
||||||
|
import { useNavbarType } from '@hooks/useNavbarType' |
||||||
|
import { useFooterType } from '@hooks/useFooterType' |
||||||
|
import { useNavbarColor } from '@hooks/useNavbarColor' |
||||||
|
|
||||||
|
// ** Styles
|
||||||
|
import '@styles/base/core/menu/menu-types/horizontal-menu.scss' |
||||||
|
|
||||||
|
const HorizontalLayout = props => { |
||||||
|
// ** Props
|
||||||
|
const { children, navbar, footer, menu, currentActiveItem, routerProps } = props |
||||||
|
|
||||||
|
// ** Hooks
|
||||||
|
const [skin, setSkin] = useSkin() |
||||||
|
const [isRtl, setIsRtl] = useRTL() |
||||||
|
const [navbarType, setNavbarType] = useNavbarType() |
||||||
|
const [footerType, setFooterType] = useFooterType() |
||||||
|
const [navbarColor, setNavbarColor] = useNavbarColor() |
||||||
|
|
||||||
|
// ** States
|
||||||
|
const [isMounted, setIsMounted] = useState(false) |
||||||
|
const [navbarScrolled, setNavbarScrolled] = useState(false) |
||||||
|
|
||||||
|
// ** Store Vars
|
||||||
|
const dispatch = useDispatch() |
||||||
|
const layoutStore = useSelector(state => state.layout) |
||||||
|
|
||||||
|
// ** Vars
|
||||||
|
const contentWidth = layoutStore.contentWidth |
||||||
|
const isHidden = layoutStore.menuHidden |
||||||
|
|
||||||
|
// ** Handles Content Width
|
||||||
|
const setContentWidth = val => dispatch(handleContentWidth(val)) |
||||||
|
|
||||||
|
// ** Handles Content Width
|
||||||
|
const setIsHidden = val => dispatch(handleMenuHidden(val)) |
||||||
|
|
||||||
|
// ** UseEffect Cleanup
|
||||||
|
const cleanup = () => { |
||||||
|
setIsMounted(false) |
||||||
|
setNavbarScrolled(false) |
||||||
|
} |
||||||
|
|
||||||
|
//** ComponentDidMount
|
||||||
|
useEffect(() => { |
||||||
|
setIsMounted(true) |
||||||
|
window.addEventListener('scroll', function () { |
||||||
|
if (window.pageYOffset > 65 && navbarScrolled === false) { |
||||||
|
setNavbarScrolled(true) |
||||||
|
} |
||||||
|
if (window.pageYOffset < 65) { |
||||||
|
setNavbarScrolled(false) |
||||||
|
} |
||||||
|
}) |
||||||
|
return () => cleanup() |
||||||
|
}, []) |
||||||
|
|
||||||
|
// ** Vars
|
||||||
|
const footerClasses = { |
||||||
|
static: 'footer-static', |
||||||
|
sticky: 'footer-fixed', |
||||||
|
hidden: 'footer-hidden' |
||||||
|
} |
||||||
|
|
||||||
|
const navbarWrapperClasses = { |
||||||
|
floating: 'navbar-floating', |
||||||
|
sticky: 'navbar-sticky', |
||||||
|
static: 'navbar-static' |
||||||
|
} |
||||||
|
|
||||||
|
const navbarClasses = { |
||||||
|
floating: 'floating-nav', |
||||||
|
sticky: 'fixed-top' |
||||||
|
} |
||||||
|
|
||||||
|
const bgColorCondition = navbarColor !== '' && navbarColor !== 'light' && navbarColor !== 'white' |
||||||
|
|
||||||
|
if (!isMounted) { |
||||||
|
return null |
||||||
|
} |
||||||
|
|
||||||
|
return ( |
||||||
|
<div |
||||||
|
className={classnames( |
||||||
|
`wrapper horizontal-layout horizontal-menu ${navbarWrapperClasses[navbarType] || 'navbar-floating'} ${ |
||||||
|
footerClasses[footerType] || 'footer-static' |
||||||
|
} menu-expanded` |
||||||
|
)} |
||||||
|
{...(isHidden ? { 'data-col': '1-column' } : {})} |
||||||
|
> |
||||||
|
<Navbar |
||||||
|
expand='lg' |
||||||
|
className={classnames('header-navbar navbar-fixed align-items-center navbar-shadow navbar-brand-center', { |
||||||
|
'navbar-scrolled': navbarScrolled |
||||||
|
})} |
||||||
|
> |
||||||
|
{!navbar && ( |
||||||
|
<div className='navbar-header d-xl-block d-none'> |
||||||
|
<ul className='nav navbar-nav'> |
||||||
|
<NavItem> |
||||||
|
<Link to='/' className='navbar-brand'> |
||||||
|
<span className='brand-logo'> |
||||||
|
<img src={themeConfig.app.appLogoImage} alt='logo' /> |
||||||
|
</span> |
||||||
|
<h2 className='brand-text mb-0'>{themeConfig.app.appName}</h2> |
||||||
|
</Link> |
||||||
|
</NavItem> |
||||||
|
</ul> |
||||||
|
</div> |
||||||
|
)} |
||||||
|
|
||||||
|
<div className='navbar-container d-flex content'> |
||||||
|
{navbar ? navbar : <NavbarComponent skin={skin} setSkin={setSkin} />} |
||||||
|
</div> |
||||||
|
</Navbar> |
||||||
|
{!isHidden ? ( |
||||||
|
<div className='horizontal-menu-wrapper'> |
||||||
|
<Navbar |
||||||
|
tag='div' |
||||||
|
expand='sm' |
||||||
|
light={skin !== 'dark'} |
||||||
|
dark={skin === 'dark' || bgColorCondition} |
||||||
|
className={classnames(`header-navbar navbar-horizontal navbar-shadow menu-border`, { |
||||||
|
[navbarClasses[navbarType]]: navbarType !== 'static', |
||||||
|
'floating-nav': (!navbarClasses[navbarType] && navbarType !== 'static') || navbarType === 'floating' |
||||||
|
})} |
||||||
|
> |
||||||
|
{menu ? menu : <MenuComponent routerProps={routerProps} currentActiveItem={currentActiveItem} />} |
||||||
|
</Navbar> |
||||||
|
</div> |
||||||
|
) : null} |
||||||
|
|
||||||
|
{children} |
||||||
|
{themeConfig.layout.customizer === true ? ( |
||||||
|
<Customizer |
||||||
|
skin={skin} |
||||||
|
setSkin={setSkin} |
||||||
|
footerType={footerType} |
||||||
|
setFooterType={setFooterType} |
||||||
|
navbarType={navbarType} |
||||||
|
setNavbarType={setNavbarType} |
||||||
|
navbarColor={navbarColor} |
||||||
|
setNavbarColor={setNavbarColor} |
||||||
|
isRtl={isRtl} |
||||||
|
setIsRtl={setIsRtl} |
||||||
|
layout={props.layout} |
||||||
|
setLayout={props.setLayout} |
||||||
|
isHidden={isHidden} |
||||||
|
setIsHidden={setIsHidden} |
||||||
|
contentWidth={contentWidth} |
||||||
|
setContentWidth={setContentWidth} |
||||||
|
transition={props.transition} |
||||||
|
setTransition={props.setTransition} |
||||||
|
themeConfig={themeConfig} |
||||||
|
/> |
||||||
|
) : null} |
||||||
|
<footer |
||||||
|
className={classnames(`footer footer-light ${footerClasses[footerType] || 'footer-static'}`, { |
||||||
|
'd-none': footerType === 'hidden' |
||||||
|
})} |
||||||
|
> |
||||||
|
{footer ? footer : <FooterComponent footerType={footerType} footerClasses={footerClasses} />} |
||||||
|
</footer> |
||||||
|
|
||||||
|
{themeConfig.layout.scrollTop === true ? ( |
||||||
|
<div className='scroll-to-top'> |
||||||
|
<ScrollToTop showUnder={300} style={{ bottom: '5%' }}> |
||||||
|
<Button className='btn-icon' color='primary'> |
||||||
|
<ArrowUp size={14} /> |
||||||
|
</Button> |
||||||
|
</ScrollToTop> |
||||||
|
</div> |
||||||
|
) : null} |
||||||
|
</div> |
||||||
|
) |
||||||
|
} |
||||||
|
export default HorizontalLayout |
@ -0,0 +1,224 @@ |
|||||||
|
// ** React Imports
|
||||||
|
import { useState, useEffect } from 'react' |
||||||
|
import { useLocation } from 'react-router-dom' |
||||||
|
|
||||||
|
// ** Store & Actions
|
||||||
|
import { useSelector, useDispatch } from 'react-redux' |
||||||
|
import { handleMenuCollapsed, handleContentWidth, handleMenuHidden } from '@store/actions/layout' |
||||||
|
|
||||||
|
// ** Third Party Components
|
||||||
|
import classnames from 'classnames' |
||||||
|
import { ArrowUp } from 'react-feather' |
||||||
|
import ScrollToTop from 'react-scroll-up' |
||||||
|
import { Navbar, Button } from 'reactstrap' |
||||||
|
|
||||||
|
// ** Configs
|
||||||
|
import themeConfig from '@configs/themeConfig' |
||||||
|
|
||||||
|
// ** Custom Components
|
||||||
|
import Customizer from '@components/customizer' |
||||||
|
import FooterComponent from './components/footer' |
||||||
|
import NavbarComponent from './components/navbar' |
||||||
|
import SidebarComponent from './components/menu/vertical-menu' |
||||||
|
|
||||||
|
// ** Custom Hooks
|
||||||
|
import { useRTL } from '@hooks/useRTL' |
||||||
|
import { useSkin } from '@hooks/useSkin' |
||||||
|
import { useNavbarType } from '@hooks/useNavbarType' |
||||||
|
import { useFooterType } from '@hooks/useFooterType' |
||||||
|
import { useNavbarColor } from '@hooks/useNavbarColor' |
||||||
|
|
||||||
|
// ** Styles
|
||||||
|
import '@styles/base/core/menu/menu-types/vertical-menu.scss' |
||||||
|
import '@styles/base/core/menu/menu-types/vertical-overlay-menu.scss' |
||||||
|
|
||||||
|
const VerticalLayout = props => { |
||||||
|
// ** Props
|
||||||
|
const { children, navbar, footer, menu, routerProps, currentActiveItem } = props |
||||||
|
|
||||||
|
// ** Hooks
|
||||||
|
const [skin, setSkin] = useSkin() |
||||||
|
const [isRtl, setIsRtl] = useRTL() |
||||||
|
const [navbarType, setNavbarType] = useNavbarType() |
||||||
|
const [footerType, setFooterType] = useFooterType() |
||||||
|
const [navbarColor, setNavbarColor] = useNavbarColor() |
||||||
|
|
||||||
|
// ** States
|
||||||
|
const [isMounted, setIsMounted] = useState(false) |
||||||
|
const [menuVisibility, setMenuVisibility] = useState(false) |
||||||
|
const [windowWidth, setWindowWidth] = useState(window.innerWidth) |
||||||
|
|
||||||
|
// ** Store Vars
|
||||||
|
const dispatch = useDispatch() |
||||||
|
const layoutStore = useSelector(state => state.layout) |
||||||
|
|
||||||
|
// ** Update Window Width
|
||||||
|
const handleWindowWidth = () => { |
||||||
|
setWindowWidth(window.innerWidth) |
||||||
|
} |
||||||
|
|
||||||
|
// ** Vars
|
||||||
|
const location = useLocation() |
||||||
|
const contentWidth = layoutStore.contentWidth |
||||||
|
const menuCollapsed = layoutStore.menuCollapsed |
||||||
|
const isHidden = layoutStore.menuHidden |
||||||
|
|
||||||
|
// ** Toggles Menu Collapsed
|
||||||
|
const setMenuCollapsed = val => dispatch(handleMenuCollapsed(val)) |
||||||
|
|
||||||
|
// ** Handles Content Width
|
||||||
|
const setContentWidth = val => dispatch(handleContentWidth(val)) |
||||||
|
|
||||||
|
// ** Handles Content Width
|
||||||
|
const setIsHidden = val => dispatch(handleMenuHidden(val)) |
||||||
|
|
||||||
|
//** This function will detect the Route Change and will hide the menu on menu item click
|
||||||
|
useEffect(() => { |
||||||
|
if (menuVisibility && windowWidth < 1200) { |
||||||
|
setMenuVisibility(false) |
||||||
|
} |
||||||
|
}, [location]) |
||||||
|
|
||||||
|
//** Sets Window Size & Layout Props
|
||||||
|
useEffect(() => { |
||||||
|
if (window !== undefined) { |
||||||
|
window.addEventListener('resize', handleWindowWidth) |
||||||
|
} |
||||||
|
}, [windowWidth]) |
||||||
|
|
||||||
|
//** ComponentDidMount
|
||||||
|
useEffect(() => { |
||||||
|
setIsMounted(true) |
||||||
|
return () => setIsMounted(false) |
||||||
|
}, []) |
||||||
|
|
||||||
|
// ** Vars
|
||||||
|
const footerClasses = { |
||||||
|
static: 'footer-static', |
||||||
|
sticky: 'footer-fixed', |
||||||
|
hidden: 'footer-hidden' |
||||||
|
} |
||||||
|
|
||||||
|
const navbarWrapperClasses = { |
||||||
|
floating: 'navbar-floating', |
||||||
|
sticky: 'navbar-sticky', |
||||||
|
static: 'navbar-static', |
||||||
|
hidden: 'navbar-hidden' |
||||||
|
} |
||||||
|
|
||||||
|
const navbarClasses = { |
||||||
|
floating: 'floating-nav', |
||||||
|
sticky: 'fixed-top', |
||||||
|
static: 'navbar-static-top', |
||||||
|
hidden: 'd-none' |
||||||
|
} |
||||||
|
|
||||||
|
const bgColorCondition = navbarColor !== '' && navbarColor !== 'light' && navbarColor !== 'white' |
||||||
|
|
||||||
|
if (!isMounted) { |
||||||
|
return null |
||||||
|
} |
||||||
|
return ( |
||||||
|
<div |
||||||
|
className={classnames( |
||||||
|
`wrapper vertical-layout ${navbarWrapperClasses[navbarType] || 'navbar-floating'} ${ |
||||||
|
footerClasses[footerType] || 'footer-static' |
||||||
|
}`,
|
||||||
|
{ |
||||||
|
// Modern Menu
|
||||||
|
'vertical-menu-modern': windowWidth >= 1200, |
||||||
|
'menu-collapsed': menuCollapsed && windowWidth >= 1200, |
||||||
|
'menu-expanded': !menuCollapsed && windowWidth > 1200, |
||||||
|
|
||||||
|
// Overlay Menu
|
||||||
|
'vertical-overlay-menu': windowWidth < 1200, |
||||||
|
'menu-hide': !menuVisibility && windowWidth < 1200, |
||||||
|
'menu-open': menuVisibility && windowWidth < 1200 |
||||||
|
} |
||||||
|
)} |
||||||
|
{...(isHidden ? { 'data-col': '1-column' } : {})} |
||||||
|
> |
||||||
|
{!isHidden ? ( |
||||||
|
<SidebarComponent |
||||||
|
skin={skin} |
||||||
|
menu={menu} |
||||||
|
menuCollapsed={menuCollapsed} |
||||||
|
menuVisibility={menuVisibility} |
||||||
|
setMenuCollapsed={setMenuCollapsed} |
||||||
|
setMenuVisibility={setMenuVisibility} |
||||||
|
routerProps={routerProps} |
||||||
|
currentActiveItem={currentActiveItem} |
||||||
|
/> |
||||||
|
) : null} |
||||||
|
|
||||||
|
<Navbar |
||||||
|
expand='lg' |
||||||
|
light={skin !== 'dark'} |
||||||
|
dark={skin === 'dark' || bgColorCondition} |
||||||
|
color={bgColorCondition ? navbarColor : undefined} |
||||||
|
className={classnames( |
||||||
|
`header-navbar navbar align-items-center ${navbarClasses[navbarType] || 'floating-nav'} navbar-shadow` |
||||||
|
)} |
||||||
|
> |
||||||
|
<div className='navbar-container d-flex content'> |
||||||
|
{navbar ? navbar : <NavbarComponent setMenuVisibility={setMenuVisibility} skin={skin} setSkin={setSkin} />} |
||||||
|
</div> |
||||||
|
</Navbar> |
||||||
|
{children} |
||||||
|
|
||||||
|
{/* Vertical Nav Menu Overlay */} |
||||||
|
<div |
||||||
|
className={classnames('sidenav-overlay', { |
||||||
|
show: menuVisibility |
||||||
|
})} |
||||||
|
onClick={() => setMenuVisibility(false)} |
||||||
|
></div> |
||||||
|
{/* Vertical Nav Menu Overlay */} |
||||||
|
|
||||||
|
{themeConfig.layout.customizer === true ? ( |
||||||
|
<Customizer |
||||||
|
skin={skin} |
||||||
|
setSkin={setSkin} |
||||||
|
footerType={footerType} |
||||||
|
setFooterType={setFooterType} |
||||||
|
navbarType={navbarType} |
||||||
|
setNavbarType={setNavbarType} |
||||||
|
navbarColor={navbarColor} |
||||||
|
setNavbarColor={setNavbarColor} |
||||||
|
isRtl={isRtl} |
||||||
|
setIsRtl={setIsRtl} |
||||||
|
layout={props.layout} |
||||||
|
setLayout={props.setLayout} |
||||||
|
isHidden={isHidden} |
||||||
|
setIsHidden={setIsHidden} |
||||||
|
contentWidth={contentWidth} |
||||||
|
setContentWidth={setContentWidth} |
||||||
|
menuCollapsed={menuCollapsed} |
||||||
|
setMenuCollapsed={setMenuCollapsed} |
||||||
|
transition={props.transition} |
||||||
|
setTransition={props.setTransition} |
||||||
|
themeConfig={themeConfig} |
||||||
|
/> |
||||||
|
) : null} |
||||||
|
<footer |
||||||
|
className={classnames(`footer footer-light ${footerClasses[footerType] || 'footer-static'}`, { |
||||||
|
'd-none': footerType === 'hidden' |
||||||
|
})} |
||||||
|
> |
||||||
|
{footer ? footer : <FooterComponent footerType={footerType} footerClasses={footerClasses} />} |
||||||
|
</footer> |
||||||
|
|
||||||
|
{themeConfig.layout.scrollTop === true ? ( |
||||||
|
<div className='scroll-to-top'> |
||||||
|
<ScrollToTop showUnder={300} style={{ bottom: '5%' }}> |
||||||
|
<Button className='btn-icon' color='primary'> |
||||||
|
<ArrowUp size={14} /> |
||||||
|
</Button> |
||||||
|
</ScrollToTop> |
||||||
|
</div> |
||||||
|
) : null} |
||||||
|
</div> |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
export default VerticalLayout |
@ -0,0 +1,22 @@ |
|||||||
|
// ** Icons Import
|
||||||
|
import { Heart } from 'react-feather' |
||||||
|
|
||||||
|
const Footer = () => { |
||||||
|
return ( |
||||||
|
<p className='clearfix mb-0'> |
||||||
|
<span className='float-md-left d-block d-md-inline-block mt-25'> |
||||||
|
COPYRIGHT © {new Date().getFullYear()}{' '} |
||||||
|
<a href='https://1.envato.market/pixinvent_portfolio' target='_blank' rel='noopener noreferrer'> |
||||||
|
Pixinvent |
||||||
|
</a> |
||||||
|
<span className='d-none d-sm-inline-block'>, All rights Reserved</span> |
||||||
|
</span> |
||||||
|
<span className='float-md-right d-none d-md-block'> |
||||||
|
Hand-crafted & Made with |
||||||
|
<Heart size={14} /> |
||||||
|
</span> |
||||||
|
</p> |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
export default Footer |
@ -0,0 +1,89 @@ |
|||||||
|
// ** React Imports
|
||||||
|
import { Fragment, useEffect } from 'react' |
||||||
|
|
||||||
|
// ** Third Party Components
|
||||||
|
import classnames from 'classnames' |
||||||
|
|
||||||
|
// ** Store & Actions
|
||||||
|
import { useSelector, useDispatch } from 'react-redux' |
||||||
|
import { handleContentWidth, handleMenuCollapsed, handleMenuHidden } from '@store/actions/layout' |
||||||
|
|
||||||
|
// ** Styles
|
||||||
|
import 'animate.css/animate.css' |
||||||
|
|
||||||
|
const LayoutWrapper = props => { |
||||||
|
// ** Props
|
||||||
|
const { layout, children, appLayout, wrapperClass, transition, routeMeta } = props |
||||||
|
|
||||||
|
// ** Store Vars
|
||||||
|
const dispatch = useDispatch() |
||||||
|
const store = useSelector(state => state) |
||||||
|
const navbarStore = store.navbar |
||||||
|
const contentWidth = store.layout.contentWidth |
||||||
|
|
||||||
|
//** Vars
|
||||||
|
const Tag = layout === 'HorizontalLayout' && !appLayout ? 'div' : Fragment |
||||||
|
|
||||||
|
// ** Clean Up Function
|
||||||
|
const cleanUp = () => { |
||||||
|
if (routeMeta) { |
||||||
|
if (routeMeta.contentWidth) { |
||||||
|
dispatch(handleContentWidth('full')) |
||||||
|
} |
||||||
|
if (routeMeta.menuCollapsed) { |
||||||
|
dispatch(handleMenuCollapsed(!routeMeta.menuCollapsed)) |
||||||
|
} |
||||||
|
if (routeMeta.menuHidden) { |
||||||
|
dispatch(handleMenuHidden(!routeMeta.menuHidden)) |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// ** ComponentDidMount
|
||||||
|
useEffect(() => { |
||||||
|
if (routeMeta) { |
||||||
|
if (routeMeta.contentWidth) { |
||||||
|
dispatch(handleContentWidth(routeMeta.contentWidth)) |
||||||
|
} |
||||||
|
if (routeMeta.menuCollapsed) { |
||||||
|
dispatch(handleMenuCollapsed(routeMeta.menuCollapsed)) |
||||||
|
} |
||||||
|
if (routeMeta.menuHidden) { |
||||||
|
dispatch(handleMenuHidden(routeMeta.menuHidden)) |
||||||
|
} |
||||||
|
} |
||||||
|
return () => cleanUp() |
||||||
|
}, []) |
||||||
|
|
||||||
|
return ( |
||||||
|
<div |
||||||
|
className={classnames('app-content content overflow-hidden', { |
||||||
|
[wrapperClass]: wrapperClass, |
||||||
|
'show-overlay': navbarStore.query.length |
||||||
|
})} |
||||||
|
> |
||||||
|
<div className='content-overlay'></div> |
||||||
|
<div className='header-navbar-shadow' /> |
||||||
|
<div |
||||||
|
className={classnames({ |
||||||
|
'content-wrapper': !appLayout, |
||||||
|
'content-area-wrapper': appLayout, |
||||||
|
'container p-0': contentWidth === 'boxed', |
||||||
|
[`animate__animated animate__${transition}`]: transition !== 'none' && transition.length |
||||||
|
})} |
||||||
|
> |
||||||
|
<Tag |
||||||
|
/*eslint-disable */ |
||||||
|
{...(layout === 'HorizontalLayout' && !appLayout |
||||||
|
? { className: classnames({ 'content-body': !appLayout }) } |
||||||
|
: {})} |
||||||
|
/*eslint-enable */ |
||||||
|
> |
||||||
|
{children} |
||||||
|
</Tag> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
export default LayoutWrapper |
@ -0,0 +1,117 @@ |
|||||||
|
// ** React Imports
|
||||||
|
import { Link, useLocation } from 'react-router-dom' |
||||||
|
|
||||||
|
// ** Third Party Components
|
||||||
|
import classnames from 'classnames' |
||||||
|
import { Dropdown, DropdownMenu, DropdownToggle } from 'reactstrap' |
||||||
|
|
||||||
|
// ** Utils
|
||||||
|
import { isNavGroupActive } from '@layouts/utils' |
||||||
|
|
||||||
|
// ** Horizontal Menu Items Component
|
||||||
|
import HorizontalNavMenuItems from './HorizontalNavMenuItems' |
||||||
|
|
||||||
|
const HorizontalNavMenuGroup = props => { |
||||||
|
// ** Props
|
||||||
|
const { |
||||||
|
item, |
||||||
|
submenu, |
||||||
|
groupActive, |
||||||
|
onMouseEnter, |
||||||
|
onMouseLeave, |
||||||
|
openDropdown, |
||||||
|
setGroupActive, |
||||||
|
activeItem, |
||||||
|
setActiveItem, |
||||||
|
routerProps, |
||||||
|
setOpenDropdown, |
||||||
|
currentActiveItem |
||||||
|
} = props |
||||||
|
|
||||||
|
// ** URL Var
|
||||||
|
const currentURL = useLocation().pathname |
||||||
|
|
||||||
|
// ** Dropdown menu modifiers
|
||||||
|
const menuModifiers = { |
||||||
|
setMaxHeight: { |
||||||
|
enabled: true, |
||||||
|
fn: data => { |
||||||
|
const pageHeight = window.innerHeight, |
||||||
|
ddTop = data.instance.reference.getBoundingClientRect().top, |
||||||
|
ddHeight = data.popper.height |
||||||
|
let maxHeight, stylesObj |
||||||
|
|
||||||
|
// ** Calculate and set height
|
||||||
|
if (pageHeight - ddTop - ddHeight - 28 < 1) { |
||||||
|
maxHeight = pageHeight - ddTop - 25 |
||||||
|
stylesObj = { |
||||||
|
maxHeight, |
||||||
|
overflowY: 'auto' |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
const ddRef = data.instance.popper.getBoundingClientRect() |
||||||
|
|
||||||
|
// ** If there is not space left to open sub menu open it to the right
|
||||||
|
if (ddRef.left + ddRef.width - (window.innerWidth - 16) >= 0) { |
||||||
|
data.instance.popper.closest('.dropdown').classList.add('openLeft') |
||||||
|
} |
||||||
|
|
||||||
|
return { |
||||||
|
...data, |
||||||
|
styles: { |
||||||
|
...stylesObj |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
return ( |
||||||
|
<Dropdown |
||||||
|
tag='li' |
||||||
|
className={classnames({ |
||||||
|
'nav-item': submenu === false, |
||||||
|
'dropdown-submenu': submenu === true, |
||||||
|
'sidebar-group-active active': |
||||||
|
isNavGroupActive(item.children, currentURL, routerProps) || groupActive.includes(item.id) |
||||||
|
})} |
||||||
|
isOpen={openDropdown.includes(item.id)} |
||||||
|
toggle={() => onMouseEnter(item.id)} |
||||||
|
onMouseEnter={() => onMouseEnter(item.id)} |
||||||
|
onMouseLeave={() => onMouseLeave(item.id)} |
||||||
|
> |
||||||
|
<DropdownToggle |
||||||
|
to='/' |
||||||
|
tag={Link} |
||||||
|
className={classnames('dropdown-toggle d-flex align-items-center', { |
||||||
|
'dropdown-item': submenu === true, |
||||||
|
'nav-link': submenu === false |
||||||
|
})} |
||||||
|
onClick={e => e.preventDefault()} |
||||||
|
> |
||||||
|
{item.icon} |
||||||
|
<span>{item.title}</span> |
||||||
|
</DropdownToggle> |
||||||
|
<DropdownMenu tag='ul' modifiers={menuModifiers}> |
||||||
|
<HorizontalNavMenuItems |
||||||
|
submenu={true} |
||||||
|
parentItem={item} |
||||||
|
items={item.children} |
||||||
|
activeItem={activeItem} |
||||||
|
groupActive={groupActive} |
||||||
|
routerProps={routerProps} |
||||||
|
openDropdown={openDropdown} |
||||||
|
onMouseEnter={onMouseEnter} |
||||||
|
onMouseLeave={onMouseLeave} |
||||||
|
setActiveItem={setActiveItem} |
||||||
|
setGroupActive={setGroupActive} |
||||||
|
isChild={true} |
||||||
|
setOpenDropdown={setOpenDropdown} |
||||||
|
currentActiveItem={currentActiveItem} |
||||||
|
/> |
||||||
|
</DropdownMenu> |
||||||
|
</Dropdown> |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
export default HorizontalNavMenuGroup |
@ -0,0 +1,23 @@ |
|||||||
|
// ** Menu Components Imports
|
||||||
|
import HorizontalNavMenuLink from './HorizontalNavMenuLink'; |
||||||
|
import HorizontalNavMenuGroup from './HorizontalNavMenuGroup'; |
||||||
|
import { resolveHorizontalNavMenuItemComponent as resolveNavItemComponent } from '@layouts/utils'; |
||||||
|
|
||||||
|
const HorizontalNavMenuItems = props => { |
||||||
|
// ** Components Object
|
||||||
|
const Components = { |
||||||
|
HorizontalNavMenuGroup, |
||||||
|
HorizontalNavMenuLink |
||||||
|
}; |
||||||
|
|
||||||
|
// ** Render Nav Items
|
||||||
|
const RenderNavItems = props.items.map((item, index) => { |
||||||
|
const TagName = Components[resolveNavItemComponent(item)]; |
||||||
|
|
||||||
|
return <TagName item={item} index={index} key={item.id} {...props} />; |
||||||
|
}); |
||||||
|
|
||||||
|
return RenderNavItems; |
||||||
|
}; |
||||||
|
|
||||||
|
export default HorizontalNavMenuItems; |
@ -0,0 +1,101 @@ |
|||||||
|
// ** React Imports
|
||||||
|
import { useEffect } from 'react'; |
||||||
|
import { NavLink, useLocation } from 'react-router-dom'; |
||||||
|
|
||||||
|
// ** Horizontal menu items array
|
||||||
|
import navigation from '@src/navigation/horizontal'; |
||||||
|
|
||||||
|
// ** Third Party Components
|
||||||
|
import classnames from 'classnames'; |
||||||
|
|
||||||
|
// 추후 서버 통신을 통한 메뉴 구성 필요.
|
||||||
|
import basis from '@src/navigation/basis'; |
||||||
|
|
||||||
|
// ** Utils
|
||||||
|
import { isNavLinkActive, search, getAllParents } from '@layouts/utils'; |
||||||
|
|
||||||
|
const HorizontalNavMenuLink = ({ |
||||||
|
item, |
||||||
|
setOpenDropdown, |
||||||
|
setGroupActive, |
||||||
|
activeItem, |
||||||
|
setActiveItem, |
||||||
|
routerProps, |
||||||
|
currentActiveItem, |
||||||
|
isChild |
||||||
|
}) => { |
||||||
|
// ** Conditional Link Tag, if item has newTab or externalLink props use <a> tag else use NavLink
|
||||||
|
const LinkTag = item.externalLink ? 'a' : NavLink; |
||||||
|
|
||||||
|
// ** URL Vars
|
||||||
|
const location = useLocation(); |
||||||
|
const currentURL = location.pathname; |
||||||
|
|
||||||
|
const navLinkActive = isNavLinkActive(item.navLink, currentURL, routerProps); |
||||||
|
|
||||||
|
// ** Get parents of current items
|
||||||
|
const searchParents = (basis, currentURL) => { |
||||||
|
const parents = search(basis, currentURL, routerProps); // Search for parent object
|
||||||
|
const allParents = getAllParents(parents, 'id'); // Parents Object to Parents Array
|
||||||
|
allParents.pop(); |
||||||
|
return allParents; |
||||||
|
}; |
||||||
|
|
||||||
|
// ** Remove all items from OpenDropdown array
|
||||||
|
const resetOpenDropdowns = () => setOpenDropdown([]); |
||||||
|
|
||||||
|
// ** On mount update active group array
|
||||||
|
useEffect(() => { |
||||||
|
if (currentActiveItem !== null) { |
||||||
|
setActiveItem(currentActiveItem); |
||||||
|
const arr = searchParents(basis, currentURL); |
||||||
|
setGroupActive([...arr]); |
||||||
|
} |
||||||
|
}, [location]); |
||||||
|
|
||||||
|
return ( |
||||||
|
<li |
||||||
|
className={classnames('nav-item', { |
||||||
|
active: item.navLink === activeItem, |
||||||
|
disabled: item.disabled |
||||||
|
})} |
||||||
|
onClick={resetOpenDropdowns} |
||||||
|
> |
||||||
|
<LinkTag |
||||||
|
className={classnames('d-flex align-items-center', { |
||||||
|
'dropdown-item': isChild, |
||||||
|
'nav-link': !isChild |
||||||
|
})} |
||||||
|
tag={LinkTag} |
||||||
|
target={item.newTab ? '_blank' : undefined} |
||||||
|
/*eslint-disable */ |
||||||
|
{...(item.externalLink === true |
||||||
|
? { |
||||||
|
href: item.navLink || '/' |
||||||
|
} |
||||||
|
: { |
||||||
|
to: item.navLink || '/', |
||||||
|
isActive: (match, location) => { |
||||||
|
if (!match) { |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
if ( |
||||||
|
match.url && |
||||||
|
match.url !== '' && |
||||||
|
match.url === item.navLink |
||||||
|
) { |
||||||
|
currentActiveItem = item.navLink; |
||||||
|
} |
||||||
|
} |
||||||
|
})} |
||||||
|
/*eslint-enable */ |
||||||
|
> |
||||||
|
{item.icon} |
||||||
|
<span>{item.title}</span> |
||||||
|
</LinkTag> |
||||||
|
</li> |
||||||
|
); |
||||||
|
}; |
||||||
|
|
||||||
|
export default HorizontalNavMenuLink; |
@ -0,0 +1,52 @@ |
|||||||
|
// ** React Imports
|
||||||
|
import { useState } from 'react' |
||||||
|
|
||||||
|
// ** Horizontal Menu Array
|
||||||
|
import navigation from '@src/navigation/horizontal' |
||||||
|
|
||||||
|
// ** Horizontal Menu Components
|
||||||
|
import HorizontalNavMenuItems from './HorizontalNavMenuItems' |
||||||
|
|
||||||
|
const HorizontalMenu = ({ currentActiveItem, routerProps }) => { |
||||||
|
// ** States
|
||||||
|
const [activeItem, setActiveItem] = useState(null) |
||||||
|
const [groupActive, setGroupActive] = useState([]) |
||||||
|
const [openDropdown, setOpenDropdown] = useState([]) |
||||||
|
|
||||||
|
// ** On mouse enter push the ID to openDropdown array
|
||||||
|
const onMouseEnter = id => { |
||||||
|
const arr = openDropdown |
||||||
|
arr.push(id) |
||||||
|
setOpenDropdown([...arr]) |
||||||
|
} |
||||||
|
|
||||||
|
// ** On mouse leave remove the ID to openDropdown array
|
||||||
|
const onMouseLeave = id => { |
||||||
|
const arr = openDropdown |
||||||
|
arr.splice(arr.indexOf(id), 1) |
||||||
|
setOpenDropdown([...arr]) |
||||||
|
} |
||||||
|
|
||||||
|
return ( |
||||||
|
<div className='navbar-container main-menu-content'> |
||||||
|
<ul className='nav navbar-nav' id='main-menu-navigation'> |
||||||
|
<HorizontalNavMenuItems |
||||||
|
submenu={false} |
||||||
|
items={navigation} |
||||||
|
activeItem={activeItem} |
||||||
|
groupActive={groupActive} |
||||||
|
routerProps={routerProps} |
||||||
|
onMouseEnter={onMouseEnter} |
||||||
|
onMouseLeave={onMouseLeave} |
||||||
|
openDropdown={openDropdown} |
||||||
|
setActiveItem={setActiveItem} |
||||||
|
setGroupActive={setGroupActive} |
||||||
|
setOpenDropdown={setOpenDropdown} |
||||||
|
currentActiveItem={currentActiveItem} |
||||||
|
/> |
||||||
|
</ul> |
||||||
|
</div> |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
export default HorizontalMenu |
@ -0,0 +1,65 @@ |
|||||||
|
// ** React Imports
|
||||||
|
import { useEffect } from 'react' |
||||||
|
import { NavLink } from 'react-router-dom' |
||||||
|
|
||||||
|
// ** Third Party Components
|
||||||
|
import { Disc, X, Circle } from 'react-feather' |
||||||
|
|
||||||
|
// ** Config
|
||||||
|
import themeConfig from '@configs/themeConfig' |
||||||
|
|
||||||
|
const VerticalMenuHeader = props => { |
||||||
|
// ** Props
|
||||||
|
const { menuCollapsed, setMenuCollapsed, setMenuVisibility, setGroupOpen, menuHover } = props |
||||||
|
|
||||||
|
// ** Reset open group
|
||||||
|
useEffect(() => { |
||||||
|
if (!menuHover && menuCollapsed) setGroupOpen([]) |
||||||
|
}, [menuHover, menuCollapsed]) |
||||||
|
|
||||||
|
// ** Menu toggler component
|
||||||
|
const Toggler = () => { |
||||||
|
if (!menuCollapsed) { |
||||||
|
return ( |
||||||
|
<Disc |
||||||
|
size={20} |
||||||
|
data-tour='toggle-icon' |
||||||
|
className='text-primary toggle-icon d-none d-xl-block' |
||||||
|
onClick={() => setMenuCollapsed(true)} |
||||||
|
/> |
||||||
|
) |
||||||
|
} else { |
||||||
|
return ( |
||||||
|
<Circle |
||||||
|
size={20} |
||||||
|
data-tour='toggle-icon' |
||||||
|
className='text-primary toggle-icon d-none d-xl-block' |
||||||
|
onClick={() => setMenuCollapsed(false)} |
||||||
|
/> |
||||||
|
) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return ( |
||||||
|
<div className='navbar-header'> |
||||||
|
<ul className='nav navbar-nav flex-row'> |
||||||
|
<li className='nav-item mr-auto'> |
||||||
|
<NavLink to='/' className='navbar-brand'> |
||||||
|
<span className='brand-logo'> |
||||||
|
<img src={themeConfig.app.appLogoImage} alt='logo' /> |
||||||
|
</span> |
||||||
|
<h2 className='brand-text mb-0'>{themeConfig.app.appName}</h2> |
||||||
|
</NavLink> |
||||||
|
</li> |
||||||
|
<li className='nav-item nav-toggle'> |
||||||
|
<div className='nav-link modern-nav-toggle cursor-pointer'> |
||||||
|
<Toggler /> |
||||||
|
<X onClick={() => setMenuVisibility(false)} className='toggle-icon icon-x d-block d-xl-none' size={20} /> |
||||||
|
</div> |
||||||
|
</li> |
||||||
|
</ul> |
||||||
|
</div> |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
export default VerticalMenuHeader |
@ -0,0 +1,142 @@ |
|||||||
|
// ** React Imports
|
||||||
|
import { Link, useLocation } from 'react-router-dom' |
||||||
|
|
||||||
|
// ** Third Party Components
|
||||||
|
import classnames from 'classnames' |
||||||
|
import { Collapse, Badge } from 'reactstrap' |
||||||
|
|
||||||
|
// ** Vertical Menu Items Component
|
||||||
|
import VerticalNavMenuItems from './VerticalNavMenuItems' |
||||||
|
|
||||||
|
// ** Utils
|
||||||
|
import { isNavGroupActive, getAllParents } from '@layouts/utils' |
||||||
|
|
||||||
|
const VerticalNavMenuGroup = ({ |
||||||
|
item, |
||||||
|
groupActive, |
||||||
|
setGroupActive, |
||||||
|
activeItem, |
||||||
|
setActiveItem, |
||||||
|
groupOpen, |
||||||
|
setGroupOpen, |
||||||
|
parentItem, |
||||||
|
menuCollapsed, |
||||||
|
menuHover, |
||||||
|
routerProps, |
||||||
|
currentActiveItem |
||||||
|
}) => { |
||||||
|
// ** Current Val
|
||||||
|
const currentURL = useLocation().pathname |
||||||
|
|
||||||
|
// ** Toggles Open Group
|
||||||
|
const toggleOpenGroup = (item, parentItem) => { |
||||||
|
let openArr = groupOpen |
||||||
|
let allParents |
||||||
|
|
||||||
|
if (parentItem) { |
||||||
|
allParents = getAllParents(parentItem, 'id') |
||||||
|
allParents.pop() |
||||||
|
} |
||||||
|
|
||||||
|
// ** If user clicked on menu group inside already opened group i.g. when user click on blog group inside pages group
|
||||||
|
if (groupOpen && allParents && groupOpen[0] === allParents[0]) { |
||||||
|
groupOpen.includes(item) ? openArr.splice(openArr.indexOf(item), 1) : openArr.push(item) |
||||||
|
} else { |
||||||
|
openArr = [] |
||||||
|
if (!groupOpen.includes(item)) { |
||||||
|
openArr.push(item) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// ** Set Open Group
|
||||||
|
setGroupOpen([...openArr]) |
||||||
|
} |
||||||
|
|
||||||
|
// ** Toggle Active Group
|
||||||
|
const toggleActiveGroup = (item, parentItem) => { |
||||||
|
let activeArr = groupActive |
||||||
|
let allParents |
||||||
|
|
||||||
|
if (parentItem) { |
||||||
|
allParents = getAllParents(parentItem, 'id') |
||||||
|
activeArr = allParents |
||||||
|
} else { |
||||||
|
activeArr.includes(item) ? activeArr.splice(activeArr.indexOf(item), 1) : activeArr.push(item) |
||||||
|
} |
||||||
|
|
||||||
|
// ** Set open group removing any activegroup item present in opengroup state
|
||||||
|
const openArr = groupOpen.filter(val => !activeArr.includes(val)) |
||||||
|
setGroupOpen([...openArr]) |
||||||
|
|
||||||
|
// ** Set Active Group
|
||||||
|
setGroupActive([...activeArr]) |
||||||
|
} |
||||||
|
|
||||||
|
// ** On Group Item Click
|
||||||
|
const onCollapseClick = (e, item) => { |
||||||
|
if ((groupActive && groupActive.includes(item.id)) || isNavGroupActive(item.children, currentURL, routerProps)) { |
||||||
|
toggleActiveGroup(item.id) |
||||||
|
} else { |
||||||
|
toggleOpenGroup(item.id, parentItem) |
||||||
|
} |
||||||
|
|
||||||
|
e.preventDefault() |
||||||
|
} |
||||||
|
|
||||||
|
// ** Returns condition to add open class
|
||||||
|
const openClassCondition = id => { |
||||||
|
if ((menuCollapsed && menuHover) || menuCollapsed === false) { |
||||||
|
if (groupActive.includes(id) || groupOpen.includes(item.id)) { |
||||||
|
return true |
||||||
|
} |
||||||
|
} else if (groupActive.includes(id) && menuCollapsed && menuHover === false) { |
||||||
|
return false |
||||||
|
} else { |
||||||
|
return null |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return ( |
||||||
|
<li |
||||||
|
className={classnames('nav-item has-sub', { |
||||||
|
open: openClassCondition(item.id), |
||||||
|
'menu-collapsed-open': groupActive.includes(item.id), |
||||||
|
'sidebar-group-active': groupActive.includes(item.id) || groupOpen.includes(item.id) |
||||||
|
})} |
||||||
|
> |
||||||
|
<Link className='d-flex align-items-center' to='/' onClick={e => onCollapseClick(e, item)}> |
||||||
|
{item.icon} |
||||||
|
<span className='menu-title text-truncate'>{item.title}</span> |
||||||
|
|
||||||
|
{item.badge && item.badgeText ? ( |
||||||
|
<Badge className='ml-auto mr-1' color={item.badge} pill> |
||||||
|
{item.badgeText} |
||||||
|
</Badge> |
||||||
|
) : null} |
||||||
|
</Link> |
||||||
|
|
||||||
|
{/* Render Child Recursively Through VerticalNavMenuItems Component */} |
||||||
|
<ul className='menu-content'> |
||||||
|
<Collapse isOpen={(groupActive && groupActive.includes(item.id)) || (groupOpen && groupOpen.includes(item.id))}> |
||||||
|
<VerticalNavMenuItems |
||||||
|
items={item.children} |
||||||
|
groupActive={groupActive} |
||||||
|
setGroupActive={setGroupActive} |
||||||
|
groupOpen={groupOpen} |
||||||
|
setGroupOpen={setGroupOpen} |
||||||
|
toggleActiveGroup={toggleActiveGroup} |
||||||
|
parentItem={item} |
||||||
|
menuCollapsed={menuCollapsed} |
||||||
|
menuHover={menuHover} |
||||||
|
routerProps={routerProps} |
||||||
|
currentActiveItem={currentActiveItem} |
||||||
|
activeItem={activeItem} |
||||||
|
setActiveItem={setActiveItem} |
||||||
|
/> |
||||||
|
</Collapse> |
||||||
|
</ul> |
||||||
|
</li> |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
export default VerticalNavMenuGroup |
@ -0,0 +1,27 @@ |
|||||||
|
// ** Vertical Menu Components
|
||||||
|
import VerticalNavMenuLink from './VerticalNavMenuLink' |
||||||
|
import VerticalNavMenuGroup from './VerticalNavMenuGroup' |
||||||
|
import VerticalNavMenuSectionHeader from './VerticalNavMenuSectionHeader' |
||||||
|
|
||||||
|
// ** Utils
|
||||||
|
import { resolveVerticalNavMenuItemComponent as resolveNavItemComponent } from '@layouts/utils' |
||||||
|
|
||||||
|
const VerticalMenuNavItems = props => { |
||||||
|
// ** Components Object
|
||||||
|
const Components = { |
||||||
|
VerticalNavMenuSectionHeader, |
||||||
|
VerticalNavMenuGroup, |
||||||
|
VerticalNavMenuLink |
||||||
|
} |
||||||
|
|
||||||
|
// ** Render Nav Menu Items
|
||||||
|
const RenderNavItems = props.items.map((item, index) => { |
||||||
|
const TagName = Components[resolveNavItemComponent(item)] |
||||||
|
|
||||||
|
return <TagName key={item.id || item.header} item={item} {...props} /> |
||||||
|
}) |
||||||
|
|
||||||
|
return RenderNavItems |
||||||
|
} |
||||||
|
|
||||||
|
export default VerticalMenuNavItems |
@ -0,0 +1,129 @@ |
|||||||
|
// ** React Imports
|
||||||
|
// ** Utils
|
||||||
|
import { getAllParents, search } from '@layouts/utils'; |
||||||
|
import analysis from '@src/navigation/analysis'; |
||||||
|
//추후 서버 통신으로 데이터 받아와야 함.
|
||||||
|
import basis from '@src/navigation/basis'; |
||||||
|
import statics from '@src/navigation/statics'; |
||||||
|
import system from '@src/navigation/system'; |
||||||
|
import classnames from 'classnames'; |
||||||
|
import { useEffect } from 'react'; |
||||||
|
import { matchPath, NavLink, useLocation } from 'react-router-dom'; |
||||||
|
// ** Third Party Components
|
||||||
|
import { Badge } from 'reactstrap'; |
||||||
|
|
||||||
|
const VerticalNavMenuLink = ({ |
||||||
|
item, |
||||||
|
groupActive, |
||||||
|
setGroupActive, |
||||||
|
activeItem, |
||||||
|
setActiveItem, |
||||||
|
groupOpen, |
||||||
|
setGroupOpen, |
||||||
|
toggleActiveGroup, |
||||||
|
parentItem, |
||||||
|
routerProps, |
||||||
|
currentActiveItem |
||||||
|
}) => { |
||||||
|
// ** Conditional Link Tag, if item has newTab or externalLink props use <a> tag else use NavLink
|
||||||
|
const LinkTag = item.externalLink ? 'a' : NavLink; |
||||||
|
|
||||||
|
// ** URL Vars
|
||||||
|
const location = useLocation(); |
||||||
|
const currentURL = location.pathname; |
||||||
|
|
||||||
|
const naviData = [...basis, ...statics, ...system, ...analysis]; |
||||||
|
|
||||||
|
// console.log(naviData);
|
||||||
|
|
||||||
|
// ** To match path
|
||||||
|
const match = matchPath(currentURL, { |
||||||
|
path: `${item.navLink}/:param`, |
||||||
|
exact: true, |
||||||
|
strict: false |
||||||
|
}); |
||||||
|
|
||||||
|
// ** Search for current item parents
|
||||||
|
const searchParents = (naviData, currentURL) => { |
||||||
|
const parents = search(naviData, currentURL, routerProps); // Search for parent object
|
||||||
|
const allParents = getAllParents(parents, 'id'); // Parents Object to Parents Array
|
||||||
|
return allParents; |
||||||
|
}; |
||||||
|
|
||||||
|
// ** URL Vars
|
||||||
|
const resetActiveGroup = navLink => { |
||||||
|
const parents = search(naviData, navLink, match); |
||||||
|
toggleActiveGroup(item.id, parents); |
||||||
|
}; |
||||||
|
|
||||||
|
// ** Reset Active & Open Group Arrays
|
||||||
|
const resetActiveAndOpenGroups = () => { |
||||||
|
setGroupActive([]); |
||||||
|
setGroupOpen([]); |
||||||
|
}; |
||||||
|
|
||||||
|
// ** Checks url & updates active item
|
||||||
|
useEffect(() => { |
||||||
|
if (currentActiveItem !== null) { |
||||||
|
setActiveItem(currentActiveItem); |
||||||
|
const arr = searchParents(naviData, currentURL); |
||||||
|
setGroupActive([...arr]); |
||||||
|
} |
||||||
|
}, [location]); |
||||||
|
|
||||||
|
return ( |
||||||
|
<li |
||||||
|
className={classnames({ |
||||||
|
'nav-item': !item.children, |
||||||
|
disabled: item.disabled, |
||||||
|
active: item.navLink === activeItem |
||||||
|
})} |
||||||
|
> |
||||||
|
<LinkTag |
||||||
|
className='d-flex align-items-center' |
||||||
|
target={item.newTab ? '_blank' : undefined} |
||||||
|
/*eslint-disable */ |
||||||
|
{...(item.externalLink === true |
||||||
|
? { |
||||||
|
href: item.navLink || '/' |
||||||
|
} |
||||||
|
: { |
||||||
|
to: item.navLink || '/', |
||||||
|
isActive: (match, location) => { |
||||||
|
if (!match) { |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
if ( |
||||||
|
match.url && |
||||||
|
match.url !== '' && |
||||||
|
match.url === item.navLink |
||||||
|
) { |
||||||
|
currentActiveItem = item.navLink; |
||||||
|
} |
||||||
|
} |
||||||
|
})} |
||||||
|
/*eslint-enable */ |
||||||
|
onClick={e => { |
||||||
|
if (!item.navLink.length) { |
||||||
|
e.preventDefault(); |
||||||
|
} |
||||||
|
parentItem |
||||||
|
? resetActiveGroup(item.navLink) |
||||||
|
: resetActiveAndOpenGroups(); |
||||||
|
}} |
||||||
|
> |
||||||
|
{item.icon} |
||||||
|
<span className='menu-item text-truncate'>{item.title}</span> |
||||||
|
|
||||||
|
{item.badge && item.badgeText ? ( |
||||||
|
<Badge className='ml-auto mr-1' color={item.badge} pill> |
||||||
|
{item.badgeText} |
||||||
|
</Badge> |
||||||
|
) : null} |
||||||
|
</LinkTag> |
||||||
|
</li> |
||||||
|
); |
||||||
|
}; |
||||||
|
|
||||||
|
export default VerticalNavMenuLink; |
@ -0,0 +1,13 @@ |
|||||||
|
// ** Third Party Components
|
||||||
|
import { MoreHorizontal } from 'react-feather' |
||||||
|
|
||||||
|
const VerticalNavMenuSectionHeader = ({ item, index }) => { |
||||||
|
return ( |
||||||
|
<li className='navigation-header'> |
||||||
|
<span>{item.header}</span> |
||||||
|
<MoreHorizontal className='feather-more-horizontal' /> |
||||||
|
</li> |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
export default VerticalNavMenuSectionHeader |
@ -0,0 +1,131 @@ |
|||||||
|
// ** React Imports
|
||||||
|
import { Fragment, useState, useRef, useEffect } from 'react'; |
||||||
|
|
||||||
|
// ** Vertical Menu Items Array
|
||||||
|
import navigation from '@src/navigation/vertical'; |
||||||
|
|
||||||
|
//추후 서버 통신으로 데이터 받아와야 함.
|
||||||
|
import basis from '@src/navigation/basis'; |
||||||
|
import statics from '@src/navigation/statics'; |
||||||
|
import system from '@src/navigation/system'; |
||||||
|
import analysis from '@src/navigation/analysis'; |
||||||
|
|
||||||
|
// ** Third Party Components
|
||||||
|
import classnames from 'classnames'; |
||||||
|
import PerfectScrollbar from 'react-perfect-scrollbar'; |
||||||
|
|
||||||
|
// ** Vertical Menu Components
|
||||||
|
import VerticalMenuHeader from './VerticalMenuHeader'; |
||||||
|
import VerticalNavMenuItems from './VerticalNavMenuItems'; |
||||||
|
import { useSelector } from 'react-redux'; |
||||||
|
|
||||||
|
const Sidebar = props => { |
||||||
|
const { topMenuCd } = useSelector(state => state.menuState); |
||||||
|
|
||||||
|
useEffect(() => { |
||||||
|
console.log('>>>>>>>>>>>>>>', topMenuCd); |
||||||
|
navData(); |
||||||
|
}, [topMenuCd]); |
||||||
|
|
||||||
|
const navData = () => { |
||||||
|
if (topMenuCd === 'basis') { |
||||||
|
return basis; |
||||||
|
} else if (topMenuCd === 'system') { |
||||||
|
return system; |
||||||
|
} else if (topMenuCd === 'statics') { |
||||||
|
return statics; |
||||||
|
} else if (topMenuCd === 'analysis') { |
||||||
|
return analysis; |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
// ** Props
|
||||||
|
const { menuCollapsed, routerProps, menu, currentActiveItem, skin } = props; |
||||||
|
|
||||||
|
// ** States
|
||||||
|
const [groupOpen, setGroupOpen] = useState([]); |
||||||
|
const [groupActive, setGroupActive] = useState([]); |
||||||
|
const [activeItem, setActiveItem] = useState(null); |
||||||
|
|
||||||
|
// ** Menu Hover State
|
||||||
|
const [menuHover, setMenuHover] = useState(false); |
||||||
|
|
||||||
|
// ** Ref
|
||||||
|
const shadowRef = useRef(null); |
||||||
|
|
||||||
|
// ** Function to handle Mouse Enter
|
||||||
|
const onMouseEnter = () => { |
||||||
|
if (menuCollapsed) { |
||||||
|
setMenuHover(true); |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
// ** Scroll Menu
|
||||||
|
const scrollMenu = container => { |
||||||
|
if (shadowRef && container.scrollTop > 0) { |
||||||
|
if (!shadowRef.current.classList.contains('d-block')) { |
||||||
|
shadowRef.current.classList.add('d-block'); |
||||||
|
} |
||||||
|
} else { |
||||||
|
if (shadowRef.current.classList.contains('d-block')) { |
||||||
|
shadowRef.current.classList.remove('d-block'); |
||||||
|
} |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
return ( |
||||||
|
<Fragment> |
||||||
|
<div |
||||||
|
className={classnames( |
||||||
|
'main-menu menu-fixed menu-accordion menu-shadow', |
||||||
|
{ |
||||||
|
expanded: menuHover || menuCollapsed === false, |
||||||
|
'menu-light': skin !== 'semi-dark' && skin !== 'dark', |
||||||
|
'menu-dark': skin === 'semi-dark' || skin === 'dark' |
||||||
|
} |
||||||
|
)} |
||||||
|
onMouseEnter={onMouseEnter} |
||||||
|
onMouseLeave={() => setMenuHover(false)} |
||||||
|
> |
||||||
|
{menu ? ( |
||||||
|
menu |
||||||
|
) : ( |
||||||
|
<Fragment> |
||||||
|
{/* Vertical Menu Header */} |
||||||
|
<VerticalMenuHeader |
||||||
|
setGroupOpen={setGroupOpen} |
||||||
|
menuHover={menuHover} |
||||||
|
{...props} |
||||||
|
/> |
||||||
|
{/* Vertical Menu Header Shadow */} |
||||||
|
<div className='shadow-bottom' ref={shadowRef}></div> |
||||||
|
{/* Perfect Scrollbar */} |
||||||
|
<PerfectScrollbar |
||||||
|
className='main-menu-content pal-main-menu-content' |
||||||
|
options={{ wheelPropagation: false }} |
||||||
|
onScrollY={container => scrollMenu(container)} |
||||||
|
> |
||||||
|
<ul className='navigation navigation-main pal-navigation-main'> |
||||||
|
<VerticalNavMenuItems |
||||||
|
items={navData()} |
||||||
|
groupActive={groupActive} |
||||||
|
setGroupActive={setGroupActive} |
||||||
|
activeItem={activeItem} |
||||||
|
setActiveItem={setActiveItem} |
||||||
|
groupOpen={groupOpen} |
||||||
|
setGroupOpen={setGroupOpen} |
||||||
|
routerProps={routerProps} |
||||||
|
menuCollapsed={menuCollapsed} |
||||||
|
menuHover={menuHover} |
||||||
|
currentActiveItem={currentActiveItem} |
||||||
|
/> |
||||||
|
</ul> |
||||||
|
</PerfectScrollbar> |
||||||
|
</Fragment> |
||||||
|
)} |
||||||
|
</div> |
||||||
|
</Fragment> |
||||||
|
); |
||||||
|
}; |
||||||
|
|
||||||
|
export default Sidebar; |
@ -0,0 +1,117 @@ |
|||||||
|
// ** Dropdowns Imports
|
||||||
|
import { Fragment } from 'react'; |
||||||
|
// ** Third Party Components
|
||||||
|
import { Menu, Moon, Sun } from 'react-feather'; |
||||||
|
import { useDispatch, useSelector } from 'react-redux'; |
||||||
|
import { Nav, NavItem, NavLink } from 'reactstrap'; |
||||||
|
import * as Actions from '../../../../modules/menu/actions/menuAction'; |
||||||
|
import UserDropdown from './UserDropdown'; |
||||||
|
|
||||||
|
const NavbarUser = props => { |
||||||
|
// ** Props
|
||||||
|
const { skin, setSkin, setMenuVisibility } = props; |
||||||
|
const dispatch = useDispatch(); |
||||||
|
|
||||||
|
const { topMenuCd } = useSelector(state => state.menuState); |
||||||
|
|
||||||
|
// ** Function to toggle Theme (Light/Dark)
|
||||||
|
const ThemeToggler = () => { |
||||||
|
if (skin === 'dark') { |
||||||
|
return <Sun className='ficon' onClick={() => setSkin('light')} />; |
||||||
|
} else { |
||||||
|
return <Moon className='ficon' onClick={() => setSkin('dark')} />; |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
const handlerTopMenu = type => { |
||||||
|
dispatch(Actions.dispatchTopMenu(type)); |
||||||
|
}; |
||||||
|
|
||||||
|
return ( |
||||||
|
<Fragment> |
||||||
|
<ul className='navbar-nav d-xl-none d-flex align-items-center'> |
||||||
|
<NavItem className='mobile-menu mr-auto'> |
||||||
|
<NavLink |
||||||
|
className='nav-menu-main menu-toggle hidden-xs is-active' |
||||||
|
onClick={() => setMenuVisibility(true)} |
||||||
|
> |
||||||
|
<Menu className='ficon' /> |
||||||
|
</NavLink> |
||||||
|
</NavItem> |
||||||
|
</ul> |
||||||
|
<Nav tabs className='header-main-menu'> |
||||||
|
<NavItem> |
||||||
|
<NavLink |
||||||
|
onClick={e => handlerTopMenu('basis')} |
||||||
|
active={topMenuCd === 'basis'} |
||||||
|
// onClick={() => {
|
||||||
|
// toggle('1')
|
||||||
|
// }}
|
||||||
|
> |
||||||
|
기초 정보 관리 |
||||||
|
</NavLink> |
||||||
|
</NavItem> |
||||||
|
{/* <NavItem> |
||||||
|
<NavLink |
||||||
|
onClick={e => handlerTopMenu('system')} |
||||||
|
active={topMenuCd === 'system'} |
||||||
|
// onClick={() => {
|
||||||
|
// toggle('1')
|
||||||
|
// }}
|
||||||
|
> |
||||||
|
시스템 관리 |
||||||
|
</NavLink> |
||||||
|
</NavItem> */} |
||||||
|
{/* <NavItem> |
||||||
|
<NavLink |
||||||
|
onClick={e => handlerTopMenu('statics')} |
||||||
|
active={topMenuCd === 'statics'} |
||||||
|
> |
||||||
|
통계 |
||||||
|
</NavLink> |
||||||
|
</NavItem> */} |
||||||
|
<NavItem> |
||||||
|
<NavLink |
||||||
|
onClick={e => handlerTopMenu('analysis')} |
||||||
|
active={topMenuCd === 'analysis'} |
||||||
|
// onClick={() => {
|
||||||
|
// toggle('3')
|
||||||
|
// }}
|
||||||
|
> |
||||||
|
비행 이력 시스템 |
||||||
|
</NavLink> |
||||||
|
</NavItem> |
||||||
|
<NavItem> |
||||||
|
<NavLink |
||||||
|
onClick={() => window.open('/control', '_blank')} |
||||||
|
// active={active === '2'}
|
||||||
|
// onClick={() => {
|
||||||
|
// toggle('2')
|
||||||
|
// }}
|
||||||
|
> |
||||||
|
드론 관제 시스템 |
||||||
|
</NavLink> |
||||||
|
</NavItem> |
||||||
|
</Nav> |
||||||
|
{/* <div className='bookmark-wrapper d-flex align-items-center'> |
||||||
|
<NavItem className='d-none d-lg-block'> |
||||||
|
<NavLink className='nav-link-style'> |
||||||
|
<ThemeToggler /> |
||||||
|
</NavLink> |
||||||
|
</NavItem> |
||||||
|
</div> */} |
||||||
|
{/* <div className='bookmark-wrapper d-flex align-items-center'> |
||||||
|
<NavItem className='d-none d-lg-block'> |
||||||
|
<NavLink className='nav-link-style'> |
||||||
|
<ThemeToggler /> |
||||||
|
</NavLink> |
||||||
|
</NavItem> |
||||||
|
</div> */} |
||||||
|
|
||||||
|
<ul className='nav navbar-nav align-items-center ml-auto'> |
||||||
|
<UserDropdown /> |
||||||
|
</ul> |
||||||
|
</Fragment> |
||||||
|
); |
||||||
|
}; |
||||||
|
export default NavbarUser; |
@ -0,0 +1,103 @@ |
|||||||
|
// ** React Imports
|
||||||
|
// ** Custom Components
|
||||||
|
import Avatar from '@components/avatar'; |
||||||
|
// ** Default Avatar Image
|
||||||
|
import defaultAvatar from '@src/assets/images/portrait/small/avatar-s-11.jpg'; |
||||||
|
// ** Utils
|
||||||
|
import { isUserLoggedIn } from '@utils'; |
||||||
|
import { useEffect, useState } from 'react'; |
||||||
|
import { Power, User } from 'react-feather'; |
||||||
|
// ** Store & Actions
|
||||||
|
import { useDispatch, useSelector } from 'react-redux'; |
||||||
|
import { Link, useHistory } from 'react-router-dom'; |
||||||
|
// import { handleLogout } from '@store/actions/auth';
|
||||||
|
// ** Third Party Components
|
||||||
|
import { |
||||||
|
DropdownItem, |
||||||
|
DropdownMenu, |
||||||
|
DropdownToggle, |
||||||
|
UncontrolledDropdown |
||||||
|
} from 'reactstrap'; |
||||||
|
import * as Actions from '../../../../modules/account/login/actions/authAction'; |
||||||
|
|
||||||
|
const UserDropdown = () => { |
||||||
|
// ** Store Vars
|
||||||
|
const dispatch = useDispatch(); |
||||||
|
const history = useHistory(); |
||||||
|
const { isLogin, user } = useSelector(state => state.authState); |
||||||
|
|
||||||
|
const handelrLogout = async () => { |
||||||
|
dispatch(Actions.logout.request()); |
||||||
|
}; |
||||||
|
|
||||||
|
// useEffect(() => {
|
||||||
|
// console.log('[ISLOGIN :::::: ] ', isLogin);
|
||||||
|
// if (isLogin === undefined) {
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if (!isLogin) {
|
||||||
|
// history.push('/account/login');
|
||||||
|
// // window.location.href = '/';
|
||||||
|
// }
|
||||||
|
// }, [isLogin]);
|
||||||
|
|
||||||
|
// ** State
|
||||||
|
const [userData, setUserData] = useState(null); |
||||||
|
|
||||||
|
//** ComponentDidMount
|
||||||
|
useEffect(() => { |
||||||
|
if (isUserLoggedIn() !== null) { |
||||||
|
setUserData(JSON.parse(localStorage.getItem('userData'))); |
||||||
|
} |
||||||
|
}, []); |
||||||
|
|
||||||
|
//** Vars
|
||||||
|
const userAvatar = (userData && userData.avatar) || defaultAvatar; |
||||||
|
|
||||||
|
return ( |
||||||
|
<UncontrolledDropdown tag='li' className='dropdown-user nav-item'> |
||||||
|
<DropdownToggle |
||||||
|
href='/' |
||||||
|
tag='a' |
||||||
|
className='nav-link dropdown-user-link' |
||||||
|
onClick={e => e.preventDefault()} |
||||||
|
> |
||||||
|
<div className='user-nav d-sm-flex d-none'> |
||||||
|
<span className='user-name font-weight-bold'>{user?.memberName}</span> |
||||||
|
<span className='user-status'>{user?.authId}</span> |
||||||
|
</div> |
||||||
|
<Avatar img={userAvatar} imgHeight='40' imgWidth='40' status='online' /> |
||||||
|
</DropdownToggle> |
||||||
|
<DropdownMenu right> |
||||||
|
<DropdownItem tag={Link} to='#' onClick={e => e.preventDefault()}> |
||||||
|
<User size={14} className='mr-75' /> |
||||||
|
<span className='align-middle'>Profile</span> |
||||||
|
</DropdownItem> |
||||||
|
{/* <DropdownItem tag={Link} to='#' onClick={e => e.preventDefault()}> |
||||||
|
<Mail size={14} className='mr-75' /> |
||||||
|
<span className='align-middle'>Inbox</span> |
||||||
|
</DropdownItem> |
||||||
|
<DropdownItem tag={Link} to='#' onClick={e => e.preventDefault()}> |
||||||
|
<CheckSquare size={14} className='mr-75' /> |
||||||
|
<span className='align-middle'>Tasks</span> |
||||||
|
</DropdownItem> |
||||||
|
<DropdownItem tag={Link} to='#' onClick={e => e.preventDefault()}> |
||||||
|
<MessageSquare size={14} className='mr-75' /> |
||||||
|
<span className='align-middle'>Chats</span> |
||||||
|
</DropdownItem> */} |
||||||
|
<DropdownItem |
||||||
|
tag={Link} |
||||||
|
// to='/login'
|
||||||
|
to='#' |
||||||
|
onClick={handelrLogout} |
||||||
|
> |
||||||
|
<Power size={14} className='mr-75' /> |
||||||
|
<span className='align-middle'>Logout</span> |
||||||
|
</DropdownItem> |
||||||
|
</DropdownMenu> |
||||||
|
</UncontrolledDropdown> |
||||||
|
); |
||||||
|
}; |
||||||
|
|
||||||
|
export default UserDropdown; |
@ -0,0 +1,18 @@ |
|||||||
|
// ** React Imports
|
||||||
|
import { Fragment } from 'react' |
||||||
|
|
||||||
|
// ** Custom Components
|
||||||
|
import NavbarUser from './NavbarUser' |
||||||
|
|
||||||
|
const ThemeNavbar = props => { |
||||||
|
// ** Props
|
||||||
|
const { skin, setSkin, setMenuVisibility } = props |
||||||
|
|
||||||
|
return ( |
||||||
|
<Fragment> |
||||||
|
<NavbarUser skin={skin} setSkin={setSkin} setMenuVisibility={setMenuVisibility} /> |
||||||
|
</Fragment> |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
export default ThemeNavbar |
@ -0,0 +1,159 @@ |
|||||||
|
// ** React Imports
|
||||||
|
import { useContext } from 'react' |
||||||
|
import { AbilityContext } from '@src/utility/context/Can' |
||||||
|
|
||||||
|
/** |
||||||
|
* Return which component to render based on it's data/context |
||||||
|
* @param {Object} item nav menu item |
||||||
|
*/ |
||||||
|
export const resolveVerticalNavMenuItemComponent = item => { |
||||||
|
if (item.header) return 'VerticalNavMenuSectionHeader' |
||||||
|
if (item.children) return 'VerticalNavMenuGroup' |
||||||
|
return 'VerticalNavMenuLink' |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Return which component to render based on it's data/context |
||||||
|
* @param {Object} item nav menu item |
||||||
|
*/ |
||||||
|
export const resolveHorizontalNavMenuItemComponent = item => { |
||||||
|
if (item.children) return 'HorizontalNavMenuGroup' |
||||||
|
return 'HorizontalNavMenuLink' |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Check if nav-link is active |
||||||
|
* @param {Object} link nav-link object |
||||||
|
*/ |
||||||
|
// export const isNavLinkActive = (link, currentURL, match) => {
|
||||||
|
// // return currentURL === link || (URLParams && Object.keys(URLParams).length && currentURLFilter === item.navLink)
|
||||||
|
// const getFirstObjProp = obj => obj[Object.keys(obj)[0]]
|
||||||
|
// return (
|
||||||
|
// currentURL === link ||
|
||||||
|
// (match !== null && match !== undefined && match.url === `${link}/${getFirstObjProp(match.params)}`)
|
||||||
|
// )
|
||||||
|
// }
|
||||||
|
|
||||||
|
export const isNavLinkActive = (link, currentURL, routerProps) => { |
||||||
|
return ( |
||||||
|
currentURL === link || |
||||||
|
(routerProps && routerProps.meta && routerProps.meta.navLink && routerProps.meta.navLink === link) |
||||||
|
) |
||||||
|
// return currentURL === link
|
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Check if nav group is |
||||||
|
* @param {Array} children Group children |
||||||
|
*/ |
||||||
|
// export const isNavGroupActive = (children, currentURL, match) => {
|
||||||
|
// return children.some(child => {
|
||||||
|
// // If child have children => It's group => Go deeper(recursive)
|
||||||
|
// if (child.children) {
|
||||||
|
// return isNavGroupActive(child.children, currentURL, match)
|
||||||
|
// }
|
||||||
|
// // else it's link => Check for matched Route
|
||||||
|
// return isNavLinkActive(child.navLink, currentURL, match)
|
||||||
|
// })
|
||||||
|
// }
|
||||||
|
export const isNavGroupActive = (children, currentURL, routerProps) => { |
||||||
|
return children.some(child => { |
||||||
|
// If child have children => It's group => Go deeper(recursive)
|
||||||
|
if (child.children) { |
||||||
|
return isNavGroupActive(child.children, currentURL, routerProps) |
||||||
|
} |
||||||
|
// else it's link => Check for matched Route
|
||||||
|
return isNavLinkActive(child.navLink, currentURL, routerProps) |
||||||
|
}) |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Search for parent object |
||||||
|
* @param {Array} navigation Group children |
||||||
|
* @param {string} currentURL current URL |
||||||
|
*/ |
||||||
|
// export const search = (navigation, currentURL, match) => {
|
||||||
|
// let result
|
||||||
|
// navigation.some(child => {
|
||||||
|
// let children
|
||||||
|
// // If child have children => It's group => Go deeper(recursive)
|
||||||
|
// if (child.children && (children = search(child.children, currentURL, match))) {
|
||||||
|
// return (result = {
|
||||||
|
// id: child.id,
|
||||||
|
// children
|
||||||
|
// })
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // else it's link => Check for matched Route
|
||||||
|
// if (isNavLinkActive(child.navLink, currentURL, match)) {
|
||||||
|
// return (result = {
|
||||||
|
// id: child.id
|
||||||
|
// })
|
||||||
|
// }
|
||||||
|
// })
|
||||||
|
// return result
|
||||||
|
// }
|
||||||
|
|
||||||
|
export const search = (navigation, currentURL, routerProps) => { |
||||||
|
let result |
||||||
|
navigation.some(child => { |
||||||
|
let children |
||||||
|
// If child have children => It's group => Go deeper(recursive)
|
||||||
|
if (child.children && (children = search(child.children, currentURL, routerProps))) { |
||||||
|
return (result = { |
||||||
|
id: child.id, |
||||||
|
children |
||||||
|
}) |
||||||
|
} |
||||||
|
|
||||||
|
// else it's link => Check for matched Route
|
||||||
|
if (isNavLinkActive(child.navLink, currentURL, routerProps)) { |
||||||
|
return (result = { |
||||||
|
id: child.id |
||||||
|
}) |
||||||
|
} |
||||||
|
}) |
||||||
|
return result |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Loop through nested object |
||||||
|
* @param {object} obj nested object |
||||||
|
*/ |
||||||
|
export const getAllParents = (obj, match) => { |
||||||
|
const res = [] |
||||||
|
const recurse = (obj, current) => { |
||||||
|
for (const key in obj) { |
||||||
|
const value = obj[key] |
||||||
|
if (value !== undefined) { |
||||||
|
if (value && typeof value === 'object') { |
||||||
|
recurse(value, key) |
||||||
|
} else { |
||||||
|
if (key === match) { |
||||||
|
res.push(value) |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
recurse(obj) |
||||||
|
return res |
||||||
|
} |
||||||
|
|
||||||
|
export const canViewMenuGroup = item => { |
||||||
|
const ability = useContext(AbilityContext) |
||||||
|
// ! This same logic is used in canViewHorizontalNavMenuGroup and canViewHorizontalNavMenuHeaderGroup. So make sure to update logic in them as well
|
||||||
|
const hasAnyVisibleChild = item.children && item.children.some(i => ability.can(i.action, i.resource)) |
||||||
|
|
||||||
|
// ** If resource and action is defined in item => Return based on children visibility (Hide group if no child is visible)
|
||||||
|
// ** Else check for ability using provided resource and action along with checking if has any visible child
|
||||||
|
if (!(item.action && item.resource)) { |
||||||
|
return hasAnyVisibleChild |
||||||
|
} |
||||||
|
return ability.can(item.action, item.resource) && hasAnyVisibleChild |
||||||
|
} |
||||||
|
|
||||||
|
export const canViewMenuItem = item => { |
||||||
|
const ability = useContext(AbilityContext) |
||||||
|
return ability.can(item.action, item.resource) |
||||||
|
} |
@ -0,0 +1,47 @@ |
|||||||
|
// ================================================================================================ |
||||||
|
// File Name: bootstrap-extended.scss |
||||||
|
// Description: List of modified Bootstrap files. This is an actual copy of bootstrap.scss |
||||||
|
// excluding files that have not been modified. |
||||||
|
// ---------------------------------------------------------------------------------------------- |
||||||
|
// Item Name: Vuexy - Vuejs, HTML & Laravel Admin Dashboard Template |
||||||
|
// Author: PIXINVENT |
||||||
|
// Author URL: http://www.themeforest.net/user/pixinvent |
||||||
|
// ================================================================================================ |
||||||
|
|
||||||
|
@import 'bootstrap-extended/include'; // Bootstrap includes |
||||||
|
@import 'components/include'; // Components includes |
||||||
|
|
||||||
|
// Custom template mixins |
||||||
|
@import 'core/mixins/alert'; // Template custom mixins |
||||||
|
|
||||||
|
// Core CSS |
||||||
|
@import 'bootstrap-extended/reboot'; |
||||||
|
@import 'bootstrap-extended/helper'; |
||||||
|
@import 'bootstrap-extended/type'; |
||||||
|
@import 'bootstrap-extended/code'; |
||||||
|
@import 'bootstrap-extended/tables'; |
||||||
|
@import 'bootstrap-extended/forms'; |
||||||
|
@import 'bootstrap-extended/buttons'; |
||||||
|
@import 'bootstrap-extended/button-group'; |
||||||
|
|
||||||
|
// Components |
||||||
|
@import 'bootstrap-extended/dropdown'; |
||||||
|
@import 'bootstrap-extended/navbar'; |
||||||
|
@import 'bootstrap-extended/card'; |
||||||
|
@import 'bootstrap-extended/breadcrumb'; |
||||||
|
@import 'bootstrap-extended/badge'; |
||||||
|
@import 'bootstrap-extended/nav'; |
||||||
|
@import 'bootstrap-extended/alert'; |
||||||
|
@import 'bootstrap-extended/media'; |
||||||
|
@import 'bootstrap-extended/progress'; |
||||||
|
@import 'bootstrap-extended/list-group'; |
||||||
|
@import 'bootstrap-extended/toast'; |
||||||
|
@import 'bootstrap-extended/collapse'; |
||||||
|
@import 'bootstrap-extended/pagination'; |
||||||
|
|
||||||
|
// Components w/ JavaScript |
||||||
|
@import 'bootstrap-extended/modal'; |
||||||
|
@import 'bootstrap-extended/popover'; |
||||||
|
|
||||||
|
// Utility classes |
||||||
|
@import 'bootstrap-extended/utilities'; |
@ -0,0 +1,56 @@ |
|||||||
|
// Alerts |
||||||
|
|
||||||
|
.alert { |
||||||
|
font-weight: 500; |
||||||
|
border: none; |
||||||
|
padding: 0; |
||||||
|
// close |
||||||
|
&.alert-dismissible { |
||||||
|
.close { |
||||||
|
padding: 0.5rem $alert-padding-x 0.5rem $alert-padding-x; |
||||||
|
background-color: transparent !important; |
||||||
|
box-shadow: none !important; |
||||||
|
} |
||||||
|
.alert-body { |
||||||
|
padding: $alert-padding-y ($alert-padding-x * 2) $alert-padding-y $alert-padding-x; |
||||||
|
} |
||||||
|
} |
||||||
|
.close:focus { |
||||||
|
outline: 0; |
||||||
|
} |
||||||
|
|
||||||
|
.alert-link:hover { |
||||||
|
text-decoration: underline; |
||||||
|
} |
||||||
|
|
||||||
|
// For Alert Content |
||||||
|
p { |
||||||
|
font-weight: 500; |
||||||
|
padding: 2px 0; |
||||||
|
margin-bottom: 0; |
||||||
|
vertical-align: middle; |
||||||
|
} |
||||||
|
|
||||||
|
// For alert heading |
||||||
|
.alert-heading { |
||||||
|
font-weight: 600; |
||||||
|
font-size: $font-size-base; |
||||||
|
padding: $alert-padding-y $alert-padding-x; |
||||||
|
margin-bottom: 0; |
||||||
|
} |
||||||
|
.alert-body { |
||||||
|
padding: $alert-padding-y $alert-padding-x; |
||||||
|
i, |
||||||
|
svg { |
||||||
|
position: relative; |
||||||
|
top: -2px; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// For dark alert |
||||||
|
&.alert-dark { |
||||||
|
.alert-heading { |
||||||
|
@include alert-heading-bs($dark); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,90 @@ |
|||||||
|
// Badge |
||||||
|
|
||||||
|
.badge { |
||||||
|
color: $white; |
||||||
|
&[class*='badge-'] { |
||||||
|
[class*='icon-'] { |
||||||
|
line-height: 1; |
||||||
|
} |
||||||
|
|
||||||
|
a { |
||||||
|
color: $white; |
||||||
|
} |
||||||
|
|
||||||
|
// badge dropdown alignment |
||||||
|
.dropdown-toggle, |
||||||
|
&.dropdown-toggle { |
||||||
|
span, |
||||||
|
i, |
||||||
|
svg { |
||||||
|
vertical-align: text-top; |
||||||
|
} |
||||||
|
i, |
||||||
|
svg { |
||||||
|
padding-left: 0.2rem; |
||||||
|
} |
||||||
|
&::after { |
||||||
|
position: relative; |
||||||
|
top: 0; |
||||||
|
left: 0; |
||||||
|
font-size: 1rem; |
||||||
|
} |
||||||
|
} |
||||||
|
.dropdown-menu { |
||||||
|
a { |
||||||
|
color: $dropdown-color; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
i, |
||||||
|
svg { |
||||||
|
height: 12px; |
||||||
|
width: 11px; |
||||||
|
font-size: 12px; |
||||||
|
stroke-width: 3; |
||||||
|
vertical-align: top; |
||||||
|
} |
||||||
|
|
||||||
|
// square badge |
||||||
|
&.badge-square { |
||||||
|
border-radius: 0; |
||||||
|
} |
||||||
|
|
||||||
|
// badge-up |
||||||
|
// to align badge over any element |
||||||
|
&.badge-up { |
||||||
|
position: absolute; |
||||||
|
top: -11px; |
||||||
|
right: -9px; |
||||||
|
min-width: 1.429rem; |
||||||
|
min-height: 1.429rem; |
||||||
|
display: flex; |
||||||
|
align-items: center; |
||||||
|
justify-content: center; |
||||||
|
font-size: 0.786rem; |
||||||
|
line-height: 0.786; |
||||||
|
padding-left: 0.25rem; |
||||||
|
padding-right: 0.25rem; |
||||||
|
&.badge-sm { |
||||||
|
top: -0.5rem; |
||||||
|
right: -0.5rem; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// For fullscreen search |
||||||
|
.badge-icon { |
||||||
|
i, |
||||||
|
svg { |
||||||
|
font-size: 100%; |
||||||
|
margin-right: 5px; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// badge dropup pointer |
||||||
|
.dropup { |
||||||
|
.badge { |
||||||
|
cursor: pointer; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,76 @@ |
|||||||
|
.breadcrumb { |
||||||
|
&:not([class*='breadcrumb-']) { |
||||||
|
.breadcrumb-item + .breadcrumb-item { |
||||||
|
&:before { |
||||||
|
content: ' '; |
||||||
|
background-image: url(str-replace(str-replace($chevron-right, 'currentColor', $body-color), '#', '%23')); |
||||||
|
background-repeat: no-repeat; |
||||||
|
background-position: center; |
||||||
|
color: $body-color; |
||||||
|
margin-right: $breadcrumb-item-padding; |
||||||
|
background-size: 14px; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
.breadcrumb-item + .breadcrumb-item { |
||||||
|
&:before { |
||||||
|
height: 20px; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/* Component Specific */ |
||||||
|
.breadcrumb-slash { |
||||||
|
&.breadcrumb { |
||||||
|
.breadcrumb-item + .breadcrumb-item:before { |
||||||
|
content: '/'; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
.breadcrumb-dots { |
||||||
|
&.breadcrumb { |
||||||
|
.breadcrumb-item + .breadcrumb-item:before { |
||||||
|
content: '.'; |
||||||
|
position: relative; |
||||||
|
top: -4px; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
.breadcrumb-dashes { |
||||||
|
&.breadcrumb { |
||||||
|
.breadcrumb-item + .breadcrumb-item:before { |
||||||
|
content: '-'; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
.breadcrumb-pipes { |
||||||
|
&.breadcrumb { |
||||||
|
.breadcrumb-item + .breadcrumb-item:before { |
||||||
|
content: '|'; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
.breadcrumb-chevron { |
||||||
|
&.breadcrumb { |
||||||
|
.breadcrumb-item + .breadcrumb-item:before { |
||||||
|
content: ' '; |
||||||
|
background-image: url(str-replace(str-replace($chevron-right, 'currentColor', $body-color), '#', '%23')); |
||||||
|
background-repeat: no-repeat; |
||||||
|
background-position: center; |
||||||
|
color: $body-color; |
||||||
|
margin-right: $breadcrumb-item-padding; |
||||||
|
background-size: 14px; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@media (max-width: 648px) { |
||||||
|
.content-header .breadcrumb { |
||||||
|
display: none; |
||||||
|
} |
||||||
|
.breadcrumbs-top { |
||||||
|
.content-header-title { |
||||||
|
display: contents !important; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,59 @@ |
|||||||
|
// |
||||||
|
// Split button dropdowns |
||||||
|
// |
||||||
|
|
||||||
|
.dropdown-toggle-split { |
||||||
|
padding-right: $btn-padding-x / 1.9; |
||||||
|
padding-left: $btn-padding-x / 1.9; |
||||||
|
} |
||||||
|
|
||||||
|
.btn-lg + .dropdown-toggle-split, |
||||||
|
.btn-group-lg > .btn + .dropdown-toggle-split { |
||||||
|
padding-right: $input-btn-padding-x-lg / 1.75; |
||||||
|
padding-left: $input-btn-padding-x-lg / 1.75; |
||||||
|
} |
||||||
|
|
||||||
|
.btn-sm + .dropdown-toggle-split, |
||||||
|
.btn-group-sm > .btn + .dropdown-toggle-split { |
||||||
|
padding-right: $input-btn-padding-x-sm / 1.9; |
||||||
|
padding-left: $input-btn-padding-x-sm / 1.9; |
||||||
|
} |
||||||
|
|
||||||
|
// button group border |
||||||
|
.btn-group { |
||||||
|
[class*='btn-']:not([class*='btn-outline-']):not([class*='btn-flat-']):not([class*='btn-gradient-']):not([class*='btn-relief-']) { |
||||||
|
border-left-color: rgba($black, 0.08) !important; |
||||||
|
border-right-color: rgba($black, 0.08) !important; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// remove first btn group border left |
||||||
|
.btn-group |
||||||
|
> .btn:not([class*='btn-outline-']):not([class*='btn-flat-']):not([class*='btn-gradient-']):not([class*='btn-relief-']):first-child, |
||||||
|
.btn-group |
||||||
|
> .btn:not([class*='btn-outline-']):not([class*='btn-flat-']):not([class*='btn-gradient-']):not([class*='btn-relief-']):first-of-type { |
||||||
|
border-left-color: transparent !important; |
||||||
|
} |
||||||
|
|
||||||
|
// remove last btn group border right |
||||||
|
.btn-group |
||||||
|
> .btn:not([class*='btn-outline-']):not([class*='btn-flat-']):not([class*='btn-gradient-']):not([class*='btn-relief-']):last-child, |
||||||
|
.btn-group |
||||||
|
> .btn:not([class*='btn-outline-']):not([class*='btn-flat-']):not([class*='btn-gradient-']):not([class*='btn-relief-']):last-of-type { |
||||||
|
border-right-color: transparent !important; |
||||||
|
} |
||||||
|
|
||||||
|
// toggle button |
||||||
|
.btn-group-toggle { |
||||||
|
[class*='btn-outline-'] { |
||||||
|
&:not(:last-child) { |
||||||
|
border-right-width: 0 !important; |
||||||
|
} |
||||||
|
} |
||||||
|
:not([class*='btn-outline-']) { |
||||||
|
&.active, |
||||||
|
&:active { |
||||||
|
box-shadow: inset $box-shadow; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,67 @@ |
|||||||
|
// var for box shadow of gradient buttons |
||||||
|
// Buttons |
||||||
|
.btn { |
||||||
|
box-shadow: none; |
||||||
|
font-weight: 500; |
||||||
|
|
||||||
|
// gradient button on hover transition |
||||||
|
&[class*='bg-gradient-'] { |
||||||
|
transition: all 0.2s ease; |
||||||
|
&:hover { |
||||||
|
transform: translateY(-2px); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// Icon button padding |
||||||
|
&.btn-icon { |
||||||
|
padding: 0.715rem 0.736rem; |
||||||
|
} |
||||||
|
&.btn-sm { |
||||||
|
&.btn-icon { |
||||||
|
padding: 0.5rem; |
||||||
|
line-height: 0.5; |
||||||
|
} |
||||||
|
} |
||||||
|
&.btn-lg { |
||||||
|
&.btn-icon { |
||||||
|
padding: 1rem; |
||||||
|
line-height: 0.75; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
&:focus, |
||||||
|
&.focus, |
||||||
|
&:active, |
||||||
|
&.active { |
||||||
|
outline: none; |
||||||
|
box-shadow: none; |
||||||
|
} |
||||||
|
|
||||||
|
&:not(:disabled):not(.disabled):active:focus, |
||||||
|
&:not(:disabled):not(.disabled).active:focus { |
||||||
|
box-shadow: none !important; |
||||||
|
} |
||||||
|
|
||||||
|
// feather icons inside btn |
||||||
|
.feather { |
||||||
|
vertical-align: bottom; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// For Waves Input Padding |
||||||
|
.btn.waves-input-wrapper { |
||||||
|
padding: 0; |
||||||
|
} |
||||||
|
|
||||||
|
@include media-breakpoint-down(sm) { |
||||||
|
.btn-sm-block { |
||||||
|
display: block; |
||||||
|
width: 100%; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// Remove cursor-pointer from button if button is disabled |
||||||
|
// * setting it to inherit will auto adept cursor |
||||||
|
.waves-effect { |
||||||
|
cursor: inherit; |
||||||
|
} |
@ -0,0 +1,514 @@ |
|||||||
|
.card { |
||||||
|
border: none; |
||||||
|
margin-bottom: $content-padding; |
||||||
|
box-shadow: $box-shadow; |
||||||
|
transition: all 0.3s ease-in-out, background 0s, color 0s, border-color 0s; |
||||||
|
.card { |
||||||
|
box-shadow: none !important; |
||||||
|
} |
||||||
|
.card-title { |
||||||
|
font-weight: 500; |
||||||
|
font-size: 1.285rem; |
||||||
|
margin-bottom: 1.53rem; // Considering sub-title minus margin |
||||||
|
} |
||||||
|
.card-bordered { |
||||||
|
border: $card-border-width solid $card-border-color; |
||||||
|
} |
||||||
|
.card-img { |
||||||
|
object-fit: cover; |
||||||
|
} |
||||||
|
.card-img-overlay { |
||||||
|
border-radius: $card-border-radius; |
||||||
|
} |
||||||
|
|
||||||
|
//fullscreen card |
||||||
|
&.card-fullscreen { |
||||||
|
display: block; |
||||||
|
z-index: 9999; |
||||||
|
position: fixed; |
||||||
|
width: 100% !important; |
||||||
|
height: 100% !important; |
||||||
|
top: 0; |
||||||
|
right: 0; |
||||||
|
left: 0; |
||||||
|
bottom: 0; |
||||||
|
overflow: auto; |
||||||
|
} |
||||||
|
.card-body[class*='border-bottom-'] { |
||||||
|
border-bottom-width: 2px !important; |
||||||
|
} |
||||||
|
.card-img-overlay { |
||||||
|
&.bg-overlay { |
||||||
|
background: rgba($black, 0.45); |
||||||
|
} |
||||||
|
.text-muted { |
||||||
|
color: $gray-800 !important; |
||||||
|
} |
||||||
|
} |
||||||
|
&.card-minimal { |
||||||
|
border: none; |
||||||
|
box-shadow: none; |
||||||
|
} |
||||||
|
|
||||||
|
.card-header { |
||||||
|
position: relative; |
||||||
|
display: flex; |
||||||
|
align-items: center; |
||||||
|
flex-wrap: wrap; |
||||||
|
justify-content: space-between; |
||||||
|
border-bottom: none; |
||||||
|
padding: 1.5rem; |
||||||
|
background-color: transparent; |
||||||
|
.card-title { |
||||||
|
margin-bottom: 0; |
||||||
|
} |
||||||
|
|
||||||
|
.heading-elements { |
||||||
|
position: relative; |
||||||
|
top: -1px; |
||||||
|
|
||||||
|
li:not(:first-child) a { |
||||||
|
margin-left: 0.75rem; |
||||||
|
} |
||||||
|
|
||||||
|
a { |
||||||
|
&.btn { |
||||||
|
padding-top: 6px; |
||||||
|
padding-bottom: 6px; |
||||||
|
} |
||||||
|
i, |
||||||
|
svg { |
||||||
|
height: 1rem; |
||||||
|
width: 1rem; |
||||||
|
font-size: 1rem; |
||||||
|
} |
||||||
|
&[data-action='collapse'] { |
||||||
|
i, |
||||||
|
svg { |
||||||
|
transition: all 0.25s ease-out; |
||||||
|
display: inline-block; |
||||||
|
} |
||||||
|
&.rotate { |
||||||
|
i, |
||||||
|
svg { |
||||||
|
transform: rotate(-180deg); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
& + .card-content > .card-body:first-of-type, |
||||||
|
& + .card-body { |
||||||
|
padding-top: 0px; |
||||||
|
} |
||||||
|
} |
||||||
|
.card-footer { |
||||||
|
border-top: 1px solid $gray-300; |
||||||
|
background-color: transparent; |
||||||
|
} |
||||||
|
} |
||||||
|
// Card Column |
||||||
|
.card-columns { |
||||||
|
.card { |
||||||
|
margin-bottom: $spacer * 2.2; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
.card-group, |
||||||
|
.card-deck { |
||||||
|
margin-bottom: 0.75rem; |
||||||
|
} |
||||||
|
|
||||||
|
.card-head-inverse { |
||||||
|
.heading-elements { |
||||||
|
i, |
||||||
|
svg { |
||||||
|
color: $white; |
||||||
|
} |
||||||
|
} |
||||||
|
color: $white; |
||||||
|
} |
||||||
|
.card-transparent { |
||||||
|
background-color: transparent; |
||||||
|
} |
||||||
|
|
||||||
|
.text-white { |
||||||
|
.card-img-overlay { |
||||||
|
.text-muted { |
||||||
|
color: $white !important; |
||||||
|
} |
||||||
|
} |
||||||
|
code { |
||||||
|
background-color: rgba($white, 1); |
||||||
|
} |
||||||
|
.heading-elements { |
||||||
|
i, |
||||||
|
svg { |
||||||
|
color: $white; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// overlay-img-card |
||||||
|
.overlay-img-card { |
||||||
|
.card-img-overlay, |
||||||
|
img { |
||||||
|
max-height: 34.64rem; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// IE Specific CSS |
||||||
|
@media screen and (-ms-high-contrast: active), (-ms-high-contrast: none) { |
||||||
|
// img-fluid class |
||||||
|
.card-body, |
||||||
|
.card-content { |
||||||
|
min-height: 1px; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
//--------------- Advance Cards --------------- |
||||||
|
//--------------------------------------------- |
||||||
|
|
||||||
|
// Congratulations Card |
||||||
|
.card-congratulations { |
||||||
|
background: linear-gradient(118deg, rgba($primary, 1), rgba($primary, 0.7)); |
||||||
|
color: $white; |
||||||
|
|
||||||
|
// image on left |
||||||
|
.congratulations-img-left { |
||||||
|
width: 200px; |
||||||
|
position: absolute; |
||||||
|
top: 0; |
||||||
|
left: 0; |
||||||
|
|
||||||
|
@include media-breakpoint-down(xs) { |
||||||
|
width: 140px; |
||||||
|
} |
||||||
|
} |
||||||
|
// image on right |
||||||
|
.congratulations-img-right { |
||||||
|
width: 175px; |
||||||
|
position: absolute; |
||||||
|
top: 0; |
||||||
|
right: 0; |
||||||
|
|
||||||
|
@include media-breakpoint-down(xs) { |
||||||
|
width: 140px; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
.avatar { |
||||||
|
margin-bottom: 2rem; |
||||||
|
} |
||||||
|
} |
||||||
|
// congratulation medal card |
||||||
|
.congratulation-medal { |
||||||
|
position: absolute; |
||||||
|
top: 0; |
||||||
|
right: 37px; |
||||||
|
} |
||||||
|
|
||||||
|
// Deposits Card |
||||||
|
.card-deposits { |
||||||
|
.deposits-divider { |
||||||
|
margin-top: 1.8rem; |
||||||
|
margin-bottom: 1.4rem; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// Employee Task Card |
||||||
|
.card-employee-task { |
||||||
|
.employee-task { |
||||||
|
&:not(:last-child) { |
||||||
|
margin-bottom: 1.5rem; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// Developer Meetup Card |
||||||
|
.card-developer-meetup { |
||||||
|
.meetup-img-wrapper { |
||||||
|
background-color: rgba($primary, 0.1); |
||||||
|
} |
||||||
|
.meetup-header { |
||||||
|
margin-bottom: 2rem; |
||||||
|
|
||||||
|
.meetup-day { |
||||||
|
text-align: center; |
||||||
|
border-right: 1px solid $custom-control-border-color; |
||||||
|
padding-right: 1.3rem; |
||||||
|
margin-right: 1.3rem; |
||||||
|
} |
||||||
|
} |
||||||
|
.media { |
||||||
|
.avatar .avatar-content { |
||||||
|
width: 34px; |
||||||
|
height: 34px; |
||||||
|
} |
||||||
|
& + .media { |
||||||
|
margin-top: 1.2rem; |
||||||
|
} |
||||||
|
} |
||||||
|
.avatar-group { |
||||||
|
margin-top: 2rem; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// Profile Card |
||||||
|
.card-profile { |
||||||
|
text-align: center; |
||||||
|
.card-body { |
||||||
|
position: relative; |
||||||
|
padding: 5rem 2.3rem $card-spacer-y 2.3rem; |
||||||
|
|
||||||
|
.profile-image-wrapper { |
||||||
|
display: flex; |
||||||
|
justify-content: center; |
||||||
|
|
||||||
|
.profile-image { |
||||||
|
position: absolute; |
||||||
|
top: -4rem; |
||||||
|
padding: 0.5rem; |
||||||
|
border-radius: 50%; |
||||||
|
background-color: $white; |
||||||
|
box-shadow: 0 0 8px 0 rgba($black, 0.14); |
||||||
|
margin-bottom: 1.15rem; |
||||||
|
|
||||||
|
img { |
||||||
|
width: 100px; |
||||||
|
height: 100px; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
.profile-badge { |
||||||
|
margin-top: 0.8rem; |
||||||
|
margin-bottom: 0.8rem; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// Apply Job Card |
||||||
|
.card-apply-job { |
||||||
|
.apply-job-package { |
||||||
|
padding: 1.2rem; |
||||||
|
margin-bottom: 1.15rem; |
||||||
|
display: flex; |
||||||
|
align-items: center; |
||||||
|
justify-content: space-between; |
||||||
|
sup { |
||||||
|
top: -0.8rem; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// Transaction Card |
||||||
|
.card-transaction { |
||||||
|
.transaction-item { |
||||||
|
display: flex; |
||||||
|
align-items: center; |
||||||
|
justify-content: space-between; |
||||||
|
&:not(:last-child) { |
||||||
|
margin-bottom: 1.2rem; |
||||||
|
} |
||||||
|
|
||||||
|
.avatar { |
||||||
|
margin-right: 1.2rem; |
||||||
|
.avatar-content { |
||||||
|
width: 42px; |
||||||
|
height: 42px; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
.transaction-title { |
||||||
|
margin-bottom: 0.2rem; |
||||||
|
margin-top: 0.2rem; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// User Timeline Card |
||||||
|
.card-user-timeline { |
||||||
|
.user-timeline-title-icon { |
||||||
|
width: 1.714rem; |
||||||
|
height: 1.714rem; |
||||||
|
margin-right: 1.3rem; |
||||||
|
} |
||||||
|
.timeline { |
||||||
|
.timeline-item { |
||||||
|
&:last-child { |
||||||
|
.timeline-event { |
||||||
|
min-height: auto; |
||||||
|
} |
||||||
|
} |
||||||
|
&:not(:last-child) { |
||||||
|
padding-bottom: 2.3rem; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// Business Card |
||||||
|
.business-card { |
||||||
|
.business-items { |
||||||
|
&:not(:last-child) { |
||||||
|
margin-bottom: 1.3rem; |
||||||
|
} |
||||||
|
|
||||||
|
.business-item { |
||||||
|
border: 1px solid $border-color; |
||||||
|
border-radius: $border-radius; |
||||||
|
padding: 1rem 1rem 1rem 1.3rem; |
||||||
|
&:not(:last-child) { |
||||||
|
margin-bottom: 0.85rem; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// States Card |
||||||
|
.card-browser-states { |
||||||
|
.browser-states { |
||||||
|
margin-top: 2.14rem; |
||||||
|
display: flex; |
||||||
|
justify-content: space-between; |
||||||
|
align-items: center; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// App Design Card |
||||||
|
.card-app-design { |
||||||
|
.design-group { |
||||||
|
margin-bottom: 2rem; |
||||||
|
|
||||||
|
.avatar:not(:last-child) { |
||||||
|
margin-right: 0.6rem; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
.design-planning-wrapper { |
||||||
|
display: flex; |
||||||
|
align-items: center; |
||||||
|
flex-wrap: wrap; |
||||||
|
&:not(:last-child) { |
||||||
|
margin-bottom: 1.3rem; |
||||||
|
} |
||||||
|
|
||||||
|
.design-planning { |
||||||
|
padding: 0.5rem; |
||||||
|
margin-bottom: 0.7rem; |
||||||
|
text-align: center; |
||||||
|
background-color: $body-bg; |
||||||
|
border-radius: $border-radius; |
||||||
|
min-width: 6.4rem; |
||||||
|
&:not(:last-child) { |
||||||
|
margin-right: 0.7rem; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
//--------------- Statistics Card --------------- |
||||||
|
//------------------------------------------------ |
||||||
|
|
||||||
|
.card-statistics { |
||||||
|
.card-header { |
||||||
|
padding-left: 2.4rem; |
||||||
|
} |
||||||
|
.statistics-body { |
||||||
|
padding: 2rem 2.4rem 2.8rem !important; |
||||||
|
|
||||||
|
.avatar .avatar-content { |
||||||
|
width: 48px; |
||||||
|
height: 48px; |
||||||
|
|
||||||
|
.avatar-icon { |
||||||
|
width: 24px; |
||||||
|
height: 24px; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
//--------------- Analytics Card --------------- |
||||||
|
//---------------------------------------------- |
||||||
|
|
||||||
|
// Chart-dropdown Button |
||||||
|
.chart-dropdown { |
||||||
|
.btn { |
||||||
|
font-size: 1rem; |
||||||
|
font-weight: $font-weight-normal; |
||||||
|
&:after { |
||||||
|
display: none; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// Revenue Report & Budget Card |
||||||
|
.card-revenue-budget { |
||||||
|
.revenue-report-wrapper { |
||||||
|
padding: 1.286rem 1.5rem; |
||||||
|
|
||||||
|
@include media-breakpoint-up(md) { |
||||||
|
border-right: 1px solid $border-color; |
||||||
|
} |
||||||
|
|
||||||
|
#revenue-report-chart { |
||||||
|
.apexcharts-series { |
||||||
|
&[seriesName='Earning'] { |
||||||
|
transform: scaleY(0.965); |
||||||
|
} |
||||||
|
&[seriesName='Expense'] { |
||||||
|
transform: scaleY(1.035); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
.budget-wrapper { |
||||||
|
padding: 2rem 3rem; |
||||||
|
text-align: center; |
||||||
|
|
||||||
|
@include media-breakpoint-down(sm) { |
||||||
|
padding-top: 0; |
||||||
|
} |
||||||
|
|
||||||
|
.budget-dropdown { |
||||||
|
margin-bottom: 2rem; |
||||||
|
} |
||||||
|
|
||||||
|
#budget-chart { |
||||||
|
margin-top: 2rem; |
||||||
|
margin-bottom: 2rem; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// Earnings Card |
||||||
|
.earnings-card { |
||||||
|
.apexcharts-canvas .apexcharts-pie { |
||||||
|
.apexcharts-datalabel-label { |
||||||
|
font-size: 0.8rem; |
||||||
|
fill: $body-color !important; |
||||||
|
} |
||||||
|
.apexcharts-datalabel-value { |
||||||
|
fill: $headings-color; |
||||||
|
font-size: 1.286rem; |
||||||
|
font-weight: 500; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// IE Specific CSS |
||||||
|
@media screen and (-ms-high-contrast: active), (-ms-high-contrast: none) { |
||||||
|
// make icon center in avatar-content |
||||||
|
#dashboard-analytics, |
||||||
|
#statistics-card { |
||||||
|
.avatar { |
||||||
|
.avatar-content { |
||||||
|
padding: 0 !important; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,14 @@ |
|||||||
|
// Inline code |
||||||
|
code { |
||||||
|
padding: 0.1rem 0.4rem; |
||||||
|
font-size: 90%; |
||||||
|
color: $code-color; |
||||||
|
background-color: $kbd-bg; |
||||||
|
@include border-radius($border-radius/2); |
||||||
|
} |
||||||
|
pre { |
||||||
|
background-color: #f7f7f9; |
||||||
|
code { |
||||||
|
background-color: transparent !important; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,140 @@ |
|||||||
|
// For Collapse And Accordion |
||||||
|
|
||||||
|
// For collapse-title |
||||||
|
[class*='collapse-'] { |
||||||
|
.collapse-title { |
||||||
|
font-weight: 500; |
||||||
|
font-size: 1.1rem; |
||||||
|
} |
||||||
|
.card { |
||||||
|
margin-bottom: 0; |
||||||
|
&:last-of-type { |
||||||
|
margin-bottom: 0; |
||||||
|
} |
||||||
|
&:not(:last-of-type) { |
||||||
|
border-bottom: 1px solid $border-color; |
||||||
|
} |
||||||
|
.card-header { |
||||||
|
cursor: pointer; |
||||||
|
padding: 1rem 2.8rem 1rem 1rem; |
||||||
|
} |
||||||
|
.card-body { |
||||||
|
padding: 1rem; |
||||||
|
line-height: 1.5; |
||||||
|
padding-top: 0.42rem; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// For collapse title |
||||||
|
.collapse-title { |
||||||
|
color: inherit; |
||||||
|
&:hover { |
||||||
|
color: inherit; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// To add a border below collapse/accordion heading |
||||||
|
.collapse-default { |
||||||
|
.card:first-child { |
||||||
|
border-top: 0; |
||||||
|
} |
||||||
|
.card:last-child { |
||||||
|
border-bottom: 0; |
||||||
|
} |
||||||
|
.card { |
||||||
|
border-radius: 0; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// For Collapse with border |
||||||
|
|
||||||
|
.collapse-border { |
||||||
|
.card { |
||||||
|
border: 1px solid $border-color; |
||||||
|
&:not(:last-of-type) { |
||||||
|
border-bottom: 0; |
||||||
|
border-bottom-right-radius: 0; |
||||||
|
border-bottom-left-radius: 0; |
||||||
|
} |
||||||
|
&:not(:first-of-type) { |
||||||
|
border-top-left-radius: 0; |
||||||
|
border-top-right-radius: 0; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// For Collapse with shadow |
||||||
|
.collapse-shadow { |
||||||
|
box-shadow: 0 0px 4px 0 rgba($black, 0.1); |
||||||
|
padding: 0.15rem 0.75rem; |
||||||
|
border-radius: $border-radius; |
||||||
|
.card { |
||||||
|
border-radius: 0; |
||||||
|
transition: border 0.5s ease-in-out, all 0.3s ease-in-out; |
||||||
|
&.open { |
||||||
|
border-radius: 0.571rem; |
||||||
|
margin: 10px 0; |
||||||
|
border: 0; |
||||||
|
box-shadow: 0px 0px 8px 0px rgba($black, 0.1) !important; |
||||||
|
} |
||||||
|
} |
||||||
|
.card:first-child { |
||||||
|
border-top-left-radius: 0.571rem; |
||||||
|
border-top-right-radius: 0.571rem; |
||||||
|
} |
||||||
|
.card:last-child { |
||||||
|
border-bottom-left-radius: 0.571rem; |
||||||
|
border-bottom-right-radius: 0.571rem; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// For Collapse with margin |
||||||
|
.collapse-margin { |
||||||
|
.card { |
||||||
|
margin-top: 0.71rem; |
||||||
|
margin-bottom: 0.71rem; |
||||||
|
box-shadow: 0 2px 15px 0 rgba($black, 0.05) !important; |
||||||
|
border-radius: 0.358rem; |
||||||
|
border-bottom: 0 solid transparent !important; |
||||||
|
} |
||||||
|
.card-header { |
||||||
|
border-radius: 0.358rem; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// Collapse Icon & Animation |
||||||
|
.collapse-icon { |
||||||
|
.card-header { |
||||||
|
position: relative; |
||||||
|
} |
||||||
|
|
||||||
|
[data-toggle='collapse'] { |
||||||
|
&:after { |
||||||
|
position: absolute; |
||||||
|
top: 58%; |
||||||
|
right: 1rem; |
||||||
|
margin-top: -8px; |
||||||
|
background-image: url(str-replace(str-replace($chevron-down, 'currentColor', $body-color), '#', '%23')); |
||||||
|
background-repeat: no-repeat; |
||||||
|
background-position: center; |
||||||
|
background-size: 14px; |
||||||
|
width: 14px; |
||||||
|
height: 11px; |
||||||
|
content: ''; |
||||||
|
transition: all 300ms linear 0s; |
||||||
|
} |
||||||
|
|
||||||
|
&:disabled { |
||||||
|
&:before { |
||||||
|
background-image: url(str-replace(str-replace($chevron-up, 'currentColor', $body-color), '#', '%23')); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
[aria-expanded='false'] { |
||||||
|
&:after { |
||||||
|
transform: rotate(-180deg); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,255 @@ |
|||||||
|
// The dropdown menu |
||||||
|
.dropdown { |
||||||
|
[class*='btn-outline-'].dropdown-toggle.dropdown-toggle-split { |
||||||
|
border-left: 0 !important; |
||||||
|
} |
||||||
|
|
||||||
|
// If don't won't dropdown/up arrow |
||||||
|
&.no-arrow { |
||||||
|
.dropdown-toggle { |
||||||
|
&:after { |
||||||
|
display: none; |
||||||
|
} |
||||||
|
i, |
||||||
|
svg { |
||||||
|
margin-right: 0; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// dropdown menu |
||||||
|
.dropdown-menu { |
||||||
|
// border: 1px solid rgba($black, 0.05); // border opacity has been reduced to make it look same as vue's dropdown border [component page, list view page] |
||||||
|
border-radius: $dropdown-border-radius; |
||||||
|
transform: scale(1, 0); |
||||||
|
box-shadow: $dropdown-box-shadow; // this according to vue version |
||||||
|
|
||||||
|
.dropdown-item { |
||||||
|
width: auto; |
||||||
|
cursor: pointer; |
||||||
|
} |
||||||
|
|
||||||
|
// Dropdown Header |
||||||
|
.dropdown-header { |
||||||
|
font-weight: 500; |
||||||
|
line-height: 1; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
.show { |
||||||
|
> .dropdown-menu { |
||||||
|
transform: scale(1, 1); |
||||||
|
opacity: 1; |
||||||
|
display: block; |
||||||
|
} |
||||||
|
.dropdown-toggle { |
||||||
|
&:focus { |
||||||
|
box-shadow: none; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// For DD box shadow on show |
||||||
|
.btn { |
||||||
|
&.dropdown-toggle { |
||||||
|
&:focus { |
||||||
|
box-shadow: none; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
.dropdown-toggle { |
||||||
|
// changed icon caret |
||||||
|
|
||||||
|
&::after { |
||||||
|
border: none !important; |
||||||
|
content: ' '; |
||||||
|
background-image: url(str-replace(str-replace($chevron-down, 'currentColor', $white), '#', '%23')); |
||||||
|
background-repeat: no-repeat; |
||||||
|
background-position: center; |
||||||
|
background-size: 16px; |
||||||
|
color: $body-color; |
||||||
|
width: 14px; |
||||||
|
height: 11px; |
||||||
|
position: relative; |
||||||
|
top: 1px; |
||||||
|
right: 0px; |
||||||
|
left: 0.714rem; |
||||||
|
padding: 0; |
||||||
|
margin: 0; |
||||||
|
vertical-align: 0; |
||||||
|
} |
||||||
|
// arrow size according to toggle sizes |
||||||
|
&.btn-lg { |
||||||
|
&::after { |
||||||
|
background-size: 18px; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
&.btn-sm { |
||||||
|
&::after { |
||||||
|
background-size: 14px; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
&.dropdown-toggle-split { |
||||||
|
&:after { |
||||||
|
left: 0; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// hide default arrow to show custom icon DD |
||||||
|
&.nav-hide-arrow { |
||||||
|
&::after { |
||||||
|
display: none; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// Prevent the focus on the dropdown toggle when closing dropdowns |
||||||
|
&:focus { |
||||||
|
outline: 0; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// DropUp |
||||||
|
.dropup { |
||||||
|
position: relative; |
||||||
|
.dropdown-toggle { |
||||||
|
// changed icon dropup caret |
||||||
|
&::after { |
||||||
|
background-image: url(str-replace(str-replace($chevron-up, 'currentColor', $white), '#', '%23')); |
||||||
|
background-repeat: no-repeat; |
||||||
|
background-position: center; |
||||||
|
background-size: 16px; |
||||||
|
width: 14px; |
||||||
|
height: 11px; |
||||||
|
content: ''; |
||||||
|
vertical-align: 0.05rem; |
||||||
|
} |
||||||
|
} |
||||||
|
.dropdown-menu { |
||||||
|
min-width: 8rem; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// DropLeft |
||||||
|
.dropleft { |
||||||
|
.dropdown-toggle { |
||||||
|
// changed icon dropup caret |
||||||
|
&::before { |
||||||
|
border: none !important; |
||||||
|
background-image: url(str-replace(str-replace($chevron-left, 'currentColor', $white), '#', '%23')); |
||||||
|
background-repeat: no-repeat; |
||||||
|
background-position: center; |
||||||
|
background-size: 16px; |
||||||
|
width: 14px; |
||||||
|
height: 11px; |
||||||
|
content: ''; |
||||||
|
position: relative; |
||||||
|
left: 0; |
||||||
|
} |
||||||
|
} |
||||||
|
.dropdown-menu { |
||||||
|
min-width: 8rem; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// DropRight |
||||||
|
.dropright { |
||||||
|
.dropdown-toggle { |
||||||
|
// changed icon dropup caret |
||||||
|
&::after { |
||||||
|
border: none !important; |
||||||
|
background-image: url(str-replace(str-replace($chevron-right, 'currentColor', $white), '#', '%23')); |
||||||
|
background-repeat: no-repeat; |
||||||
|
background-position: center; |
||||||
|
background-size: 16px; |
||||||
|
width: 14px; |
||||||
|
height: 11px; |
||||||
|
content: ''; |
||||||
|
} |
||||||
|
} |
||||||
|
.dropdown-menu { |
||||||
|
min-width: 8rem; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// Dropdown ::before position |
||||||
|
.dropdown-menu { |
||||||
|
// Dropdown margin according to dropdown position |
||||||
|
|
||||||
|
&[x-placement='bottom-start'], |
||||||
|
&[x-placement='bottom-end'] { |
||||||
|
margin-top: $dropdown_spacing; |
||||||
|
} |
||||||
|
|
||||||
|
&[x-placement='top-start'], |
||||||
|
&[x-placement='top-end'] { |
||||||
|
margin-bottom: $dropdown_spacing; |
||||||
|
} |
||||||
|
|
||||||
|
&[x-placement='right-start'] { |
||||||
|
margin-left: $dropdown_spacing; |
||||||
|
} |
||||||
|
&[x-placement='left-start'] { |
||||||
|
margin-right: $dropdown_spacing; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// Dropdown icon |
||||||
|
.dropdown, |
||||||
|
.dropup { |
||||||
|
&.dropdown-icon-wrapper { |
||||||
|
.dropdown-toggle { |
||||||
|
&:after { |
||||||
|
display: none; |
||||||
|
} |
||||||
|
} |
||||||
|
.dropdown-menu { |
||||||
|
min-width: auto; |
||||||
|
.dropdown-item { |
||||||
|
padding: 0.5rem 1.1rem; |
||||||
|
cursor: pointer; |
||||||
|
i, |
||||||
|
svg { |
||||||
|
height: 1.3rem; |
||||||
|
width: 1.3rem; |
||||||
|
font-size: 1.3rem; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// Dropdown menu animation for Horizontal menu |
||||||
|
.horizontal-menu-wrapper .dropdown-menu, |
||||||
|
.header-navbar .dropdown-menu { |
||||||
|
animation-duration: 0.3s; |
||||||
|
animation-fill-mode: both; |
||||||
|
animation-name: slideIn; |
||||||
|
} |
||||||
|
|
||||||
|
// Hidden dropdown toggle arrow |
||||||
|
.dropdown-toggle.hide-arrow, |
||||||
|
.dropdown-toggle-hide-arrow > .dropdown-toggle { |
||||||
|
&::before, |
||||||
|
&::after { |
||||||
|
display: none; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@keyframes slideIn { |
||||||
|
0% { |
||||||
|
transform: translateY(1rem); |
||||||
|
opacity: 0; |
||||||
|
} |
||||||
|
100% { |
||||||
|
transform: translateY(0rem); |
||||||
|
opacity: 1; |
||||||
|
} |
||||||
|
0% { |
||||||
|
transform: translateY(1rem); |
||||||
|
opacity: 0; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,570 @@ |
|||||||
|
// |
||||||
|
// Labels |
||||||
|
// |
||||||
|
label { |
||||||
|
color: $headings-color; |
||||||
|
font-size: $small-font-size; |
||||||
|
} |
||||||
|
|
||||||
|
// placeholder specific scss |
||||||
|
.form-control { |
||||||
|
&::placeholder { |
||||||
|
transition: all 0.2s ease; |
||||||
|
} |
||||||
|
|
||||||
|
&:focus { |
||||||
|
&::placeholder { |
||||||
|
transform: translate(5px); |
||||||
|
transition: all 0.2s ease; |
||||||
|
} |
||||||
|
&:valid, |
||||||
|
&.is-valid { |
||||||
|
box-shadow: $input-focus-box-shadow; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
.form-control-plaintext { |
||||||
|
&:focus { |
||||||
|
outline: none; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
.custom-file-label { |
||||||
|
line-height: 1.75; |
||||||
|
height: $custom-file-height !important; |
||||||
|
&:after { |
||||||
|
height: 2.56rem; |
||||||
|
line-height: 1.75; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
.valid-tooltip, |
||||||
|
.invalid-tooltip { |
||||||
|
top: 102%; |
||||||
|
left: 5px; |
||||||
|
} |
||||||
|
|
||||||
|
/*************** |
||||||
|
* Form Group |
||||||
|
***************/ |
||||||
|
|
||||||
|
// input group !important for overriding the dark style |
||||||
|
.input-group { |
||||||
|
&:not(.bootstrap-touchspin):focus-within { |
||||||
|
box-shadow: $input-focus-box-shadow; |
||||||
|
border-radius: $input-border-radius; |
||||||
|
.form-control, |
||||||
|
.input-group-text { |
||||||
|
border-color: $primary; |
||||||
|
box-shadow: none; |
||||||
|
|
||||||
|
&.is-valid { |
||||||
|
border-color: $success; |
||||||
|
} |
||||||
|
|
||||||
|
&.is-invalid { |
||||||
|
border-color: $danger; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
&.is-valid { |
||||||
|
.input-group-text { |
||||||
|
border-color: $success !important; |
||||||
|
} |
||||||
|
&:not(.bootstrap-touchspin):focus-within { |
||||||
|
.input-group-text { |
||||||
|
border-color: $success; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
&.is-invalid { |
||||||
|
.input-group-text { |
||||||
|
border-color: $danger !important; |
||||||
|
} |
||||||
|
&:not(.bootstrap-touchspin):focus-within { |
||||||
|
.input-group-text { |
||||||
|
border-color: $danger; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
&.disabled { |
||||||
|
.input-group-text { |
||||||
|
background-color: $input-disabled-bg; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
&.round { |
||||||
|
.form-control, |
||||||
|
.input-group-text, |
||||||
|
&:focus-within { |
||||||
|
@include border-radius(1.5rem); |
||||||
|
} |
||||||
|
} |
||||||
|
&.square { |
||||||
|
.form-control, |
||||||
|
.input-group-text, |
||||||
|
&:focus-within { |
||||||
|
@include border-radius(0); |
||||||
|
} |
||||||
|
} |
||||||
|
&.round, |
||||||
|
&.square { |
||||||
|
.input-group-prepend { |
||||||
|
.input-group-text { |
||||||
|
border-top-right-radius: 0; |
||||||
|
border-bottom-right-radius: 0; |
||||||
|
} |
||||||
|
} |
||||||
|
.input-group-append { |
||||||
|
.input-group-text { |
||||||
|
border-top-left-radius: 0; |
||||||
|
border-bottom-left-radius: 0; |
||||||
|
} |
||||||
|
} |
||||||
|
.form-control { |
||||||
|
&:not(:first-child) { |
||||||
|
border-top-left-radius: 0; |
||||||
|
border-bottom-left-radius: 0; |
||||||
|
} |
||||||
|
&:not(:last-child) { |
||||||
|
border-top-right-radius: 0; |
||||||
|
border-bottom-right-radius: 0; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
&.square { |
||||||
|
.form-control, |
||||||
|
.input-group-text { |
||||||
|
@include border-radius(0); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
.input-group-text { |
||||||
|
@include transition($input-transition); |
||||||
|
} |
||||||
|
|
||||||
|
.input-group-prepend { |
||||||
|
.input-group-text { |
||||||
|
border-right: 0; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
.input-group-append { |
||||||
|
.input-group-text { |
||||||
|
border-left: 0; |
||||||
|
} |
||||||
|
&:not(:last-child) .input-group-text { |
||||||
|
border-right: 0; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// input group merge |
||||||
|
.input-group-merge { |
||||||
|
.form-control { |
||||||
|
&:not(:first-child) { |
||||||
|
padding-left: 0; |
||||||
|
border-left: 0; |
||||||
|
} |
||||||
|
|
||||||
|
&:not(:last-child) { |
||||||
|
padding-right: 0; |
||||||
|
border-right: 0; |
||||||
|
} |
||||||
|
|
||||||
|
&.is-valid { |
||||||
|
~ .input-group-append { |
||||||
|
.input-group-text { |
||||||
|
border-color: $success; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
.input-group-prepend { |
||||||
|
~ .form-control.is-valid { |
||||||
|
.input-group-text & { |
||||||
|
border-color: $success; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// Text area line height |
||||||
|
textarea { |
||||||
|
&.form-control { |
||||||
|
line-height: 1.6rem; |
||||||
|
padding: 0.8rem 1rem !important; |
||||||
|
} |
||||||
|
|
||||||
|
&.form-control-sm { |
||||||
|
padding: 0.4rem 0.857rem !important; |
||||||
|
} |
||||||
|
|
||||||
|
&.form-control-lg { |
||||||
|
padding: 1rem 1.143rem !important; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// Used for Card - Check it and remove if not used |
||||||
|
.form-actions { |
||||||
|
border-top: 1px solid darken($body-bg, 10%); |
||||||
|
padding: 20px 0; |
||||||
|
margin-top: 20px; |
||||||
|
|
||||||
|
&.filled { |
||||||
|
background-color: $body-bg; |
||||||
|
} |
||||||
|
&.center { |
||||||
|
text-align: center; |
||||||
|
} |
||||||
|
&.right { |
||||||
|
text-align: right; |
||||||
|
} |
||||||
|
|
||||||
|
&.top { |
||||||
|
border-top: 0; |
||||||
|
border-bottom: 1px solid darken($body-bg, 10%); |
||||||
|
margin-top: 0; |
||||||
|
margin-bottom: 20px; |
||||||
|
} |
||||||
|
|
||||||
|
@include media-breakpoint-down(sm) { |
||||||
|
.buttons-group { |
||||||
|
float: left !important; |
||||||
|
margin-bottom: 10px; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// Form-horizontal layout |
||||||
|
.form-horizontal { |
||||||
|
.form-group { |
||||||
|
@include media-breakpoint-up(sm) { |
||||||
|
.label-control { |
||||||
|
text-align: right; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// Select Inputs Specific SCSS |
||||||
|
select.form-control { |
||||||
|
&:not([multiple='multiple']) { |
||||||
|
background-image: url(str-replace(str-replace($chevron-down, 'currentColor', $input-border-color), '#', '%23')); |
||||||
|
background-position: calc(100% - 12px) 13px, calc(100% - 20px) 13px, 100% 0; |
||||||
|
background-size: 18px 14px, 18px 14px; |
||||||
|
background-repeat: no-repeat; |
||||||
|
-webkit-appearance: none; |
||||||
|
-moz-appearance: none; |
||||||
|
padding-right: 1.5rem; |
||||||
|
} |
||||||
|
&.form-control-lg { |
||||||
|
background-position: calc(100% - 12px) 16px, calc(100% - 20px) 16px, 100% 0; |
||||||
|
} |
||||||
|
&.form-control-sm { |
||||||
|
background-position: calc(100% - 12px) 8px, calc(100% - 20px) 8px, 100% 0; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// For customs-select remove double arrow |
||||||
|
.custom-select { |
||||||
|
-moz-appearance: none; // For firefox |
||||||
|
-webkit-appearance: none; // for chrome |
||||||
|
} |
||||||
|
|
||||||
|
// Custom Checkbox |
||||||
|
.custom-checkbox { |
||||||
|
.custom-control-label::before, |
||||||
|
.custom-control-label::after { |
||||||
|
top: 0.07rem; |
||||||
|
} |
||||||
|
|
||||||
|
.custom-control-label::after { |
||||||
|
background-size: 57%; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// Custom Radio |
||||||
|
.custom-radio { |
||||||
|
.custom-control-label::before { |
||||||
|
top: 0.1rem; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// Custom checkbox and radio in common |
||||||
|
.custom-checkbox, |
||||||
|
.custom-radio { |
||||||
|
&.custom-control { |
||||||
|
padding-left: 1.8rem; |
||||||
|
|
||||||
|
.input-group & { |
||||||
|
padding-left: 1.3rem; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
.custom-control-input { |
||||||
|
width: 1.285rem; |
||||||
|
height: 1.285rem; |
||||||
|
} |
||||||
|
|
||||||
|
.custom-control-label { |
||||||
|
font-size: $font-size-base; |
||||||
|
position: static; |
||||||
|
// vertical-align: middle; |
||||||
|
&::before, |
||||||
|
&::after { |
||||||
|
width: 18px; |
||||||
|
height: 18px; |
||||||
|
left: 0; |
||||||
|
} |
||||||
|
} |
||||||
|
.custom-control-input:checked ~ .custom-control-label::before { |
||||||
|
box-shadow: 0 2px 4px 0 rgba($custom-control-indicator-checked-bg, 0.4) !important; |
||||||
|
} |
||||||
|
|
||||||
|
.custom-control-input:disabled ~ .custom-control-label::before { |
||||||
|
border: none; |
||||||
|
box-shadow: none !important; |
||||||
|
} |
||||||
|
|
||||||
|
.custom-control-input:focus ~ .custom-control-label::before { |
||||||
|
border-color: none; |
||||||
|
box-shadow: 0 2px 4px 0 rgba($custom-control-indicator-checked-bg, 0.4) !important; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// Custom-checkbox when not disabled and active |
||||||
|
.custom-control-input:not(:disabled) { |
||||||
|
&:active ~ .custom-control-label { |
||||||
|
&::before { |
||||||
|
background-color: $primary; |
||||||
|
border-color: $primary; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/* Floating label Group */ |
||||||
|
.form-label-group { |
||||||
|
position: relative; |
||||||
|
margin-bottom: $form-group-margin-bottom; |
||||||
|
|
||||||
|
// Form-Control-Large in Floating Label Group |
||||||
|
.form-control-lg { |
||||||
|
~ label { |
||||||
|
font-size: $input-font-size; |
||||||
|
padding: 1rem; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// Form-label |
||||||
|
> label { |
||||||
|
position: absolute; |
||||||
|
top: 0; |
||||||
|
left: 0; |
||||||
|
display: block; |
||||||
|
transition: all 0.25s ease-in-out; |
||||||
|
padding: 0.6rem; |
||||||
|
pointer-events: none; |
||||||
|
cursor: text; |
||||||
|
color: rgba($black, 0.4); |
||||||
|
font-size: 0.7rem; |
||||||
|
opacity: 0; |
||||||
|
} |
||||||
|
// form-input |
||||||
|
> input, |
||||||
|
textarea { |
||||||
|
// from-input on focus change label color |
||||||
|
&:focus, |
||||||
|
&:not(:active) { |
||||||
|
&:not(:placeholder-shown) ~ label { |
||||||
|
color: rgba($primary, 1) !important; |
||||||
|
transition: all 0.25s ease-in-out; |
||||||
|
opacity: 1; |
||||||
|
} |
||||||
|
} |
||||||
|
&:not(:focus) { |
||||||
|
&:not(:placeholder-shown) ~ label { |
||||||
|
color: rgba($black, 0.4) !important; |
||||||
|
} |
||||||
|
} |
||||||
|
// form-label after entering text in input box |
||||||
|
&:not(:placeholder-shown) ~ label { |
||||||
|
padding: 0.25rem 0; |
||||||
|
top: -20px; |
||||||
|
left: 3px; |
||||||
|
} |
||||||
|
|
||||||
|
&.form-control-lg:not(:placeholder-shown) ~ label { |
||||||
|
top: -23px; |
||||||
|
} |
||||||
|
|
||||||
|
&.form-control-sm:not(:placeholder-shown) ~ label { |
||||||
|
top: -18px; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/* Switches */ |
||||||
|
|
||||||
|
.custom-switch { |
||||||
|
padding-left: 0; |
||||||
|
line-height: 1.7rem; |
||||||
|
|
||||||
|
.custom-control-label { |
||||||
|
padding-left: 3.5rem; |
||||||
|
line-height: 1.7rem; |
||||||
|
|
||||||
|
/* For bg color of switch*/ |
||||||
|
&::before { |
||||||
|
border: none; |
||||||
|
background-color: $switch-bg-color; |
||||||
|
height: 1.7rem; |
||||||
|
box-shadow: none !important; |
||||||
|
transition: opacity 0.25s ease, background-color 0.1s ease; |
||||||
|
cursor: pointer; |
||||||
|
user-select: none; |
||||||
|
top: 0; |
||||||
|
left: 0; |
||||||
|
} |
||||||
|
/*For Switch handle*/ |
||||||
|
&:after { |
||||||
|
position: absolute; |
||||||
|
top: 4px; |
||||||
|
left: 4px; |
||||||
|
box-shadow: -1px 2px 3px 0 rgba($black, 0.2); |
||||||
|
background-color: $switch-indicator-color; |
||||||
|
transition: all 0.15s ease-out; |
||||||
|
cursor: pointer; |
||||||
|
user-select: none; |
||||||
|
} |
||||||
|
|
||||||
|
/*For Switch text*/ |
||||||
|
.switch-text-left, |
||||||
|
.switch-text-right, |
||||||
|
.switch-icon-left, |
||||||
|
.switch-icon-right { |
||||||
|
position: absolute; |
||||||
|
cursor: pointer; |
||||||
|
user-select: none; |
||||||
|
line-height: 1.8; |
||||||
|
i, |
||||||
|
svg { |
||||||
|
height: 13px; |
||||||
|
width: 13px; |
||||||
|
font-size: 13px; |
||||||
|
} |
||||||
|
} |
||||||
|
.switch-text-left, |
||||||
|
.switch-icon-left { |
||||||
|
left: 6px; |
||||||
|
color: $white; |
||||||
|
opacity: 0; |
||||||
|
transform: translateX(8px); |
||||||
|
transition: opacity 0.1s ease, transform 0.15s ease; |
||||||
|
} |
||||||
|
.switch-text-right, |
||||||
|
.switch-icon-right { |
||||||
|
right: 13px; |
||||||
|
opacity: 1; |
||||||
|
transform: translateX(0px); |
||||||
|
transition: opacity 0.08s ease, transform 0.15s ease; |
||||||
|
} |
||||||
|
&:focus { |
||||||
|
outline: 0; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/*For Switch label*/ |
||||||
|
|
||||||
|
.switch-label { |
||||||
|
padding-left: 1rem; |
||||||
|
} |
||||||
|
|
||||||
|
// after its checked |
||||||
|
|
||||||
|
.custom-control-input:checked ~ .custom-control-label::before { |
||||||
|
box-shadow: none; |
||||||
|
} |
||||||
|
|
||||||
|
/*For Switch Handle Animation*/ |
||||||
|
.custom-control-input:checked ~ .custom-control-label::after { |
||||||
|
transform: translateX(1.4rem); |
||||||
|
} |
||||||
|
|
||||||
|
.custom-control-input:checked ~ .custom-control-label { |
||||||
|
.switch-text-left, |
||||||
|
.switch-icon-left { |
||||||
|
transform: translateX(0); |
||||||
|
opacity: 1; |
||||||
|
} |
||||||
|
|
||||||
|
.switch-text-right, |
||||||
|
.switch-icon-right { |
||||||
|
transform: translateX(-8px); |
||||||
|
opacity: 0; |
||||||
|
} |
||||||
|
} |
||||||
|
.custom-control-input:not(:checked) ~ .custom-control-label { |
||||||
|
.switch-text-left { |
||||||
|
opacity: 0; |
||||||
|
} |
||||||
|
.switch-text-right { |
||||||
|
opacity: 1; |
||||||
|
} |
||||||
|
} |
||||||
|
.custom-control-input:checked ~ .custom-control-label { |
||||||
|
.switch-text-right { |
||||||
|
opacity: 0; |
||||||
|
} |
||||||
|
.switch-text-left { |
||||||
|
opacity: 1; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/* Textarea with Counter */ |
||||||
|
.textarea-counter-value { |
||||||
|
background-color: $primary; |
||||||
|
color: $white; |
||||||
|
padding: 1px 6px; |
||||||
|
font-size: 0.6rem; |
||||||
|
border-radius: 0 0 5px 5px; |
||||||
|
margin-right: 1rem; |
||||||
|
} |
||||||
|
|
||||||
|
.btn.disabled-max-min { |
||||||
|
background-color: rgba($black, 0.5) !important; |
||||||
|
cursor: default; |
||||||
|
} |
||||||
|
|
||||||
|
/* Number Type Input Box Scss for - Remove arrow on hover */ |
||||||
|
input[type='number']::-webkit-inner-spin-button, |
||||||
|
input[type='number']::-webkit-outer-spin-button { |
||||||
|
-webkit-appearance: none; |
||||||
|
} |
||||||
|
|
||||||
|
// IE Specific CSS |
||||||
|
@media screen and (-ms-high-contrast: active), (-ms-high-contrast: none) { |
||||||
|
// floating Label Group |
||||||
|
.form-label-group { |
||||||
|
label { |
||||||
|
display: none; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// Bootstrap Select |
||||||
|
select.form-control { |
||||||
|
&:not([multiple='multiple']) { |
||||||
|
background: none; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// Date & Time Picker - Form Control Bg color |
||||||
|
.picker__input { |
||||||
|
&.form-control { |
||||||
|
background-color: $white; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,10 @@ |
|||||||
|
@function str-replace($string, $search, $replace: '') { |
||||||
|
$index: str-index($string, $search); |
||||||
|
|
||||||
|
@if $index { |
||||||
|
@return str-slice($string, 1, $index - 1) + $replace + |
||||||
|
str-replace(str-slice($string, $index + str-length($search)), $search, $replace); |
||||||
|
} |
||||||
|
|
||||||
|
@return $string; |
||||||
|
} |
@ -0,0 +1,106 @@ |
|||||||
|
// ================================================================================================ |
||||||
|
// File Name: helper.scss |
||||||
|
// Description: Helper classes provides template related customization. |
||||||
|
// ---------------------------------------------------------------------------------------------- |
||||||
|
// Item Name: Vuexy - Vuejs, HTML & Laravel Admin Dashboard Template |
||||||
|
// Author: PIXINVENT |
||||||
|
// Author URL: http://www.themeforest.net/user/pixinvent |
||||||
|
// ================================================================================================ |
||||||
|
|
||||||
|
// Content helpers |
||||||
|
// ------------------------- |
||||||
|
|
||||||
|
// typography page icon with list |
||||||
|
.list-style-icons { |
||||||
|
padding-left: 10px; |
||||||
|
margin-left: 0; |
||||||
|
list-style: none; |
||||||
|
> li svg, |
||||||
|
> li i { |
||||||
|
margin-right: 6px; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
//Pull the element |
||||||
|
.pull-up { |
||||||
|
transition: all 0.25s ease; |
||||||
|
|
||||||
|
&:hover { |
||||||
|
transform: translateY(-4px) scale(1.02); |
||||||
|
box-shadow: 0px 14px 24px rgba(62, 57, 107, 0.2); |
||||||
|
z-index: 30; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// Spinner classes |
||||||
|
.spinner { |
||||||
|
display: inline-block; |
||||||
|
animation: spin 1s linear infinite; |
||||||
|
} |
||||||
|
@keyframes spin { |
||||||
|
0% { |
||||||
|
transform: rotate(0deg); |
||||||
|
} |
||||||
|
100% { |
||||||
|
transform: rotate(360deg); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
.spinner-reverse { |
||||||
|
display: inline-block; |
||||||
|
animation: spin-reverse 1s linear infinite; |
||||||
|
} |
||||||
|
@keyframes spin-reverse { |
||||||
|
0% { |
||||||
|
transform: rotate(0deg); |
||||||
|
} |
||||||
|
100% { |
||||||
|
transform: rotate(-360deg); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// Bullets used in application pages |
||||||
|
.bullet { |
||||||
|
width: 1rem; |
||||||
|
height: 1rem; |
||||||
|
border-radius: 50%; |
||||||
|
display: inline-block; |
||||||
|
&.bullet-xs { |
||||||
|
width: 0.5rem; |
||||||
|
height: 0.5rem; |
||||||
|
} |
||||||
|
&.bullet-sm { |
||||||
|
width: 0.714rem; |
||||||
|
height: 0.714rem; |
||||||
|
} |
||||||
|
&.bullet-lg { |
||||||
|
width: 1.25rem; |
||||||
|
height: 1.25rem; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// Section Label - used in pages and apps |
||||||
|
.section-label { |
||||||
|
font-size: 0.85rem; |
||||||
|
color: $text-muted; |
||||||
|
text-transform: uppercase; |
||||||
|
letter-spacing: 0.6px; |
||||||
|
} |
||||||
|
|
||||||
|
// Used for table cell fit |
||||||
|
.cell-fit { |
||||||
|
width: 0.1%; |
||||||
|
white-space: nowrap; |
||||||
|
} |
||||||
|
|
||||||
|
// Card match height |
||||||
|
.match-height { |
||||||
|
> [class*='col'] { |
||||||
|
display: flex; |
||||||
|
flex-flow: column; |
||||||
|
|
||||||
|
> .card { |
||||||
|
flex: 1 1 auto; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,24 @@ |
|||||||
|
// ================================================================================================ |
||||||
|
// File Name: include.scss |
||||||
|
// Description: Common components file to include all theme specific custom components. |
||||||
|
// ---------------------------------------------------------------------------------------------- |
||||||
|
// Item Name: Vuexy - Vuejs, HTML & Laravel Admin Dashboard Template |
||||||
|
// Author: PIXINVENT |
||||||
|
// Author URL: http://www.themeforest.net/user/pixinvent |
||||||
|
// ================================================================================================ |
||||||
|
|
||||||
|
// Variables |
||||||
|
// ------------------------------ |
||||||
|
|
||||||
|
// Functions |
||||||
|
@import 'bootstrap/scss/functions'; // Bootstrap core function |
||||||
|
@import 'functions'; // Bootstrap extended function |
||||||
|
|
||||||
|
// Variables |
||||||
|
@import 'scss/variables/variables'; // Bootstrap custom variable override (for user purpose) |
||||||
|
@import 'variables'; // Bootstrap extended variable override |
||||||
|
@import 'bootstrap/scss/variables'; // Bootstrap core variable |
||||||
|
|
||||||
|
// Mixins |
||||||
|
@import 'bootstrap/scss/mixins'; // Bootstrap core mixins |
||||||
|
@import 'mixins'; // Bootstrap extended mixins |
@ -0,0 +1,101 @@ |
|||||||
|
/* =============================================================================================== |
||||||
|
File Name: list-group.scss |
||||||
|
Description: Contain list item, list group related extended SCSS. |
||||||
|
---------------------------------------------------------------------------------------------- |
||||||
|
Item Name: Vuexy - Vuejs, HTML & Laravel Admin Dashboard Template |
||||||
|
Author: PIXINVENT |
||||||
|
Author URL: http://www.themeforest.net/user/pixinvent |
||||||
|
================================================================================================*/ |
||||||
|
|
||||||
|
// Inline list style with pipeline separator |
||||||
|
|
||||||
|
ul.list-inline { |
||||||
|
li { |
||||||
|
display: inline-block; |
||||||
|
} |
||||||
|
// used in search page |
||||||
|
&.list-inline-pipe { |
||||||
|
> li + li:before { |
||||||
|
content: ' | '; |
||||||
|
padding-right: 2px; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// bootstrap list group |
||||||
|
.list-group { |
||||||
|
.list-group-item { |
||||||
|
line-height: 1.5; |
||||||
|
&.active { |
||||||
|
&:hover { |
||||||
|
background-color: $primary; |
||||||
|
} |
||||||
|
&:focus { |
||||||
|
// color: $body-color; |
||||||
|
outline: 0; |
||||||
|
&:hover { |
||||||
|
color: $white; |
||||||
|
} |
||||||
|
} |
||||||
|
small { |
||||||
|
color: $white !important; |
||||||
|
} |
||||||
|
} |
||||||
|
&:hover { |
||||||
|
background-color: $body-bg; |
||||||
|
} |
||||||
|
|
||||||
|
i, |
||||||
|
svg { |
||||||
|
position: relative; |
||||||
|
} |
||||||
|
|
||||||
|
&:not(.active):focus:active { |
||||||
|
color: inherit; |
||||||
|
} |
||||||
|
} |
||||||
|
.list-group-item-action { |
||||||
|
&.active { |
||||||
|
background-color: $primary; |
||||||
|
color: $white; |
||||||
|
&:focus { |
||||||
|
background-color: $primary; |
||||||
|
} |
||||||
|
} |
||||||
|
&:focus { |
||||||
|
background-color: $body-bg; |
||||||
|
outline: 0; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// List group with circle for pages like knowledge base |
||||||
|
&.list-group-circle { |
||||||
|
border: none; |
||||||
|
.list-group-item { |
||||||
|
border: none; |
||||||
|
position: relative; |
||||||
|
padding-left: 1.5rem; |
||||||
|
&:after { |
||||||
|
content: ' '; |
||||||
|
background-image: url(str-replace(str-replace($circle, 'currentColor', $body-color), '#', '%23')); |
||||||
|
background-repeat: no-repeat; |
||||||
|
background-position: center; |
||||||
|
color: $body-color; |
||||||
|
background-size: 10px; |
||||||
|
position: absolute; |
||||||
|
height: 10px; |
||||||
|
width: 10px; |
||||||
|
top: 1.15rem; |
||||||
|
left: 0; |
||||||
|
} |
||||||
|
&:hover { |
||||||
|
background-color: transparent; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// for drag and drop border radius on selected |
||||||
|
.list-group-item.gu-mirror { |
||||||
|
border-radius: 0; |
||||||
|
} |
@ -0,0 +1,22 @@ |
|||||||
|
.media-list { |
||||||
|
.media { |
||||||
|
padding: 1.25rem; |
||||||
|
width: 100%; |
||||||
|
margin-top: 0; |
||||||
|
.media-left { |
||||||
|
margin-right: 1rem; |
||||||
|
} |
||||||
|
.media-right { |
||||||
|
margin-left: 1rem; |
||||||
|
} |
||||||
|
} |
||||||
|
a.media { |
||||||
|
color: $gray-600 !important; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
.media-bordered { |
||||||
|
.media:not(:first-child) { |
||||||
|
border-top: 1px solid $border-color; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,13 @@ |
|||||||
|
// =============================================================================================== |
||||||
|
// File Name: mixins.scss |
||||||
|
// Description: Extended mixins file with new mixins features. |
||||||
|
// ---------------------------------------------------------------------------------------------- |
||||||
|
// Item Name: Vuexy - Vuejs, HTML & Laravel Admin Dashboard Template |
||||||
|
// Author: PIXINVENT |
||||||
|
// Author URL: http://www.themeforest.net/user/pixinvent |
||||||
|
// ================================================================================================ |
||||||
|
|
||||||
|
@import 'mixins/_type'; //(NEW) |
||||||
|
|
||||||
|
// Components |
||||||
|
@import 'mixins/_navs'; |
@ -0,0 +1,175 @@ |
|||||||
|
// Modals |
||||||
|
|
||||||
|
.modal { |
||||||
|
// Modal Header |
||||||
|
|
||||||
|
.modal-header { |
||||||
|
background-color: $body-bg; |
||||||
|
border-bottom: none; |
||||||
|
border-bottom-left-radius: 0; |
||||||
|
border-bottom-right-radius: 0; |
||||||
|
// close button |
||||||
|
|
||||||
|
.close { |
||||||
|
padding: 0.2rem 0.62rem; |
||||||
|
box-shadow: 0 5px 20px 0 rgba($black, 0.1); |
||||||
|
border-radius: $border-radius; |
||||||
|
background: $white; |
||||||
|
opacity: 1; |
||||||
|
transition: all 0.23s ease 0.1s; |
||||||
|
position: relative; |
||||||
|
transform: translate(8px, -2px); |
||||||
|
|
||||||
|
// For hover effect of close btn |
||||||
|
&:hover, |
||||||
|
&:focus, |
||||||
|
&:active { |
||||||
|
opacity: 1; |
||||||
|
outline: none; |
||||||
|
transform: translate(5px, 3px); |
||||||
|
box-shadow: none; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
// Modal Content |
||||||
|
.modal-content { |
||||||
|
border: none; |
||||||
|
// overflow: unset; updated to "visible" as close icon is not visible in IE |
||||||
|
overflow: visible; |
||||||
|
box-shadow: 0 5px 20px 0 rgba($black, 0.1); |
||||||
|
} |
||||||
|
|
||||||
|
.modal-footer { |
||||||
|
padding: $modal-inner-padding; |
||||||
|
} |
||||||
|
|
||||||
|
// modal sticky for apps |
||||||
|
&.modal-sticky { |
||||||
|
bottom: 0; |
||||||
|
right: 0; |
||||||
|
top: auto; |
||||||
|
left: auto; |
||||||
|
height: auto; |
||||||
|
position: fixed; |
||||||
|
.modal-header { |
||||||
|
display: flex; |
||||||
|
align-items: center; |
||||||
|
justify-content: space-between; |
||||||
|
} |
||||||
|
.modal-dialog { |
||||||
|
margin-right: #{$content-padding} !important; |
||||||
|
box-shadow: 0px 0px 24px 0 rgba($black, 0.25); |
||||||
|
border-radius: $border-radius; |
||||||
|
} |
||||||
|
.modal-actions { |
||||||
|
background: transparent; |
||||||
|
box-shadow: none; |
||||||
|
line-height: 0; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// Modal XS |
||||||
|
.modal-xs { |
||||||
|
max-width: 300px; |
||||||
|
} |
||||||
|
|
||||||
|
// Modal XL |
||||||
|
@media (min-width: 1200px) { |
||||||
|
.modal-xl { |
||||||
|
margin-left: 3%; |
||||||
|
margin-right: 3%; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// Slide In Modal // |
||||||
|
.modal-slide-in, |
||||||
|
.modal-slide-in .modal { |
||||||
|
padding: 0 !important; |
||||||
|
overflow: hidden !important; |
||||||
|
} |
||||||
|
|
||||||
|
.modal-slide-in { |
||||||
|
.modal-dialog { |
||||||
|
position: fixed; |
||||||
|
top: 0; |
||||||
|
right: 0; |
||||||
|
bottom: 0; |
||||||
|
left: auto; |
||||||
|
margin: 0; |
||||||
|
max-width: none; |
||||||
|
width: ($modal-slide-in-width-sm - 5); |
||||||
|
|
||||||
|
.modal-content { |
||||||
|
padding-bottom: ($modal-title-line-height * $close-font-size) + $modal-header-padding-y; |
||||||
|
padding-top: ($modal-title-line-height * $close-font-size) + $modal-header-padding-y; |
||||||
|
overflow: auto; |
||||||
|
border-radius: 0; |
||||||
|
height: 100%; |
||||||
|
} |
||||||
|
|
||||||
|
.modal-body { |
||||||
|
padding-bottom: 0; |
||||||
|
padding-top: 0; |
||||||
|
margin: auto 0; |
||||||
|
flex-grow: 0; |
||||||
|
} |
||||||
|
|
||||||
|
@media (min-width: (map-get($grid-breakpoints, sm))) { |
||||||
|
width: $modal-slide-in-width; |
||||||
|
} |
||||||
|
|
||||||
|
&.sidebar-sm { |
||||||
|
width: $modal-slide-in-width-sm; |
||||||
|
} |
||||||
|
&.sidebar-lg { |
||||||
|
@media (min-width: (map-get($grid-breakpoints, sm))) { |
||||||
|
width: $modal-slide-in-width-lg; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
.close { |
||||||
|
top: $modal-header-padding-y / 2; |
||||||
|
z-index: 10; |
||||||
|
transform: none; |
||||||
|
position: absolute; |
||||||
|
top: 1.5rem; |
||||||
|
right: $modal-header-padding-x; |
||||||
|
margin: 0; |
||||||
|
padding: 0 !important; |
||||||
|
line-height: 0.5; |
||||||
|
transform: translate(0, -50%); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// Slide from Right |
||||||
|
.modal-slide-in.fade .modal-dialog, |
||||||
|
.modal-slide-in .modal.fade .modal-dialog { |
||||||
|
transform: translateX(100%); |
||||||
|
transition: transform 0.1s ease-out; |
||||||
|
} |
||||||
|
|
||||||
|
.modal-slide-in.show .modal-dialog, |
||||||
|
.modal-slide-in .modal.show .modal-dialog { |
||||||
|
transform: translateX(0) !important; |
||||||
|
transition: transform 0.1s ease-out; |
||||||
|
} |
||||||
|
|
||||||
|
// To remove Max-width of XS Modal in Small Screen |
||||||
|
|
||||||
|
@media (max-width: 576px) { |
||||||
|
.modal { |
||||||
|
padding-right: 1rem; |
||||||
|
padding-left: 1rem; |
||||||
|
.modal-xs, |
||||||
|
.modal-sm { |
||||||
|
max-width: unset; |
||||||
|
} |
||||||
|
&.modal-sticky .modal-dialog { |
||||||
|
margin-right: 0.2rem !important; |
||||||
|
margin-left: 0.2rem; |
||||||
|
margin-bottom: 3rem; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,272 @@ |
|||||||
|
// Component nav and nav/pill tabs |
||||||
|
|
||||||
|
.nav { |
||||||
|
border-radius: 0.25rem; |
||||||
|
// for component navs |
||||||
|
// to wrap border around nav component |
||||||
|
&.wrap-border { |
||||||
|
border: 1px solid $nav-component-border-color; |
||||||
|
li.nav-header { |
||||||
|
margin: 0 0.5rem; |
||||||
|
} |
||||||
|
li.nav-item, |
||||||
|
div { |
||||||
|
padding: 2px 0.714rem; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
&.nav-left { |
||||||
|
.nav-item .nav-link { |
||||||
|
justify-content: flex-start; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
&.nav-right { |
||||||
|
.nav-item .nav-link { |
||||||
|
justify-content: flex-end; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// Square Border |
||||||
|
&.square-border { |
||||||
|
border-radius: 0; |
||||||
|
.nav-item { |
||||||
|
.nav-link.active { |
||||||
|
border-radius: 0; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// for main menu toggle lock |
||||||
|
.modern-nav-toggle { |
||||||
|
padding: 0; |
||||||
|
margin: 1.571rem 0; |
||||||
|
} |
||||||
|
|
||||||
|
// Dropdown without background need arrow color changes |
||||||
|
.dropdown.show { |
||||||
|
.dropdown-toggle { |
||||||
|
&::after { |
||||||
|
background-image: url(str-replace(str-replace($chevron-down, 'currentColor', $white), '#', '%23')); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
.dropdown-toggle { |
||||||
|
&:not(.active) { |
||||||
|
&::after { |
||||||
|
background-image: url(str-replace(str-replace($chevron-down, 'currentColor', $body-color), '#', '%23')); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
.nav-pills, |
||||||
|
.nav-tabs { |
||||||
|
// if icon added inside nav-link |
||||||
|
.nav-link { |
||||||
|
display: flex; |
||||||
|
align-items: center; |
||||||
|
justify-content: center; |
||||||
|
i, |
||||||
|
svg { |
||||||
|
margin-right: 0.5rem; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
// nav pills |
||||||
|
.nav-pills { |
||||||
|
margin-bottom: 1rem; |
||||||
|
// nav item of nav pill |
||||||
|
.nav-link { |
||||||
|
padding: $btn-padding-y $btn-padding-x; |
||||||
|
font-size: $btn-font-size; |
||||||
|
line-height: $btn-font-size; |
||||||
|
border: 1px solid transparent; |
||||||
|
color: $headings-color; |
||||||
|
&.active { |
||||||
|
border-color: $nav-pills-link-active-bg; |
||||||
|
box-shadow: 0 4px 18px -4px rgba($nav-pills-link-active-bg, 0.65); |
||||||
|
} |
||||||
|
&.disabled { |
||||||
|
color: $nav-link-disabled-color; |
||||||
|
} |
||||||
|
&.dropdown-toggle::after { |
||||||
|
top: 1px; |
||||||
|
left: 1px; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
&.dropdown { |
||||||
|
&.show { |
||||||
|
.nav-link { |
||||||
|
color: $white; |
||||||
|
} |
||||||
|
.dropdown-item { |
||||||
|
&.active { |
||||||
|
&:hover { |
||||||
|
color: $primary; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// Justified Pills |
||||||
|
&.nav-justified { |
||||||
|
@include nav-justified; |
||||||
|
@include nav-tabs-justified; |
||||||
|
.nav-link { |
||||||
|
display: block; |
||||||
|
|
||||||
|
&.active { |
||||||
|
border: none; |
||||||
|
|
||||||
|
&:hover, |
||||||
|
&:focus { |
||||||
|
border: none; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// Basic Nav Tabs |
||||||
|
.nav-tabs { |
||||||
|
margin-bottom: 1rem; |
||||||
|
position: relative; |
||||||
|
// Basic nav item |
||||||
|
.nav-item { |
||||||
|
position: relative; |
||||||
|
} |
||||||
|
.nav-link { |
||||||
|
color: $body-color; |
||||||
|
border: none; |
||||||
|
min-width: auto; |
||||||
|
font-weight: 450; |
||||||
|
padding: 0.61rem 1.2rem; |
||||||
|
border-radius: 0; |
||||||
|
position: relative; |
||||||
|
overflow: hidden; |
||||||
|
|
||||||
|
&:after { |
||||||
|
content: ''; |
||||||
|
|
||||||
|
position: absolute; |
||||||
|
bottom: 0; |
||||||
|
left: 0; |
||||||
|
width: 100%; |
||||||
|
height: 3px; |
||||||
|
background: linear-gradient(30deg, rgba($primary, 1), rgba($primary, 0.5)) !important; |
||||||
|
transition: transform 0.3s; |
||||||
|
transform: translate3d(0, 150%, 0); |
||||||
|
} |
||||||
|
&.active { |
||||||
|
position: relative; |
||||||
|
color: $primary; |
||||||
|
|
||||||
|
&:after { |
||||||
|
transform: translate3d(0, 0, 0); |
||||||
|
// box-shadow: 0 0 8px 0 rgba($primary, 0.5) !important; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
&.dropdown-toggle { |
||||||
|
&::after { |
||||||
|
top: 1px; |
||||||
|
left: 1px; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
// Justified Tabs |
||||||
|
&.nav-justified { |
||||||
|
@include nav-justified; |
||||||
|
@include nav-tabs-justified; |
||||||
|
|
||||||
|
.nav-item { |
||||||
|
a.nav-link { |
||||||
|
display: block; |
||||||
|
border-radius: 0; |
||||||
|
|
||||||
|
&.active { |
||||||
|
border: none; |
||||||
|
} |
||||||
|
&:hover { |
||||||
|
border-color: transparent; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// Nav Tabs Vertical |
||||||
|
.nav-vertical { |
||||||
|
overflow: hidden; |
||||||
|
.nav.nav-tabs { |
||||||
|
// nav item styles for vertical nav tabs |
||||||
|
.nav-item { |
||||||
|
.nav-link { |
||||||
|
margin-bottom: 0; |
||||||
|
&:after { |
||||||
|
transform: rotate(90deg) translate3d(0, 150%, 0); |
||||||
|
left: 70%; |
||||||
|
} |
||||||
|
&.active { |
||||||
|
&:after { |
||||||
|
left: auto; |
||||||
|
right: -1.4rem; |
||||||
|
transform: rotate(90deg) translate3d(0, 225%, 0); |
||||||
|
top: 1.25rem; |
||||||
|
width: 2.14rem; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// vertical nav left tabs |
||||||
|
&.nav-left { |
||||||
|
float: left; |
||||||
|
display: table; |
||||||
|
margin-right: 1rem; |
||||||
|
|
||||||
|
~ .tab-content { |
||||||
|
.tab-pane { |
||||||
|
display: none; |
||||||
|
overflow-y: auto; |
||||||
|
padding-left: 1rem; |
||||||
|
&.active { |
||||||
|
display: block; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// vertical right nav tabs |
||||||
|
&.nav-right { |
||||||
|
float: right; |
||||||
|
display: table; |
||||||
|
margin-left: 1rem; |
||||||
|
|
||||||
|
.nav-item { |
||||||
|
.nav-link { |
||||||
|
&.active { |
||||||
|
&:after { |
||||||
|
left: -0.9rem; |
||||||
|
transform: rotate(90deg) translate3d(0, 10%, 0); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
~ .tab-content { |
||||||
|
.tab-pane { |
||||||
|
display: none; |
||||||
|
overflow-y: auto; |
||||||
|
padding-right: 1rem; |
||||||
|
&.active { |
||||||
|
display: block; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,682 @@ |
|||||||
|
/* =============================================================================================== |
||||||
|
File Name: navbar.scss |
||||||
|
Description: Contain header navigation bar, vertical main navigation bar and |
||||||
|
horiznotal main navigation bar related SCSS. |
||||||
|
---------------------------------------------------------------------------------------------- |
||||||
|
Item Name: Vuexy - Vuejs, HTML & Laravel Admin Dashboard Template |
||||||
|
Author: PIXINVENT |
||||||
|
Author URL: http://www.themeforest.net/user/pixinvent |
||||||
|
================================================================================================*/ |
||||||
|
|
||||||
|
@function set-navbar-text-color($color) { |
||||||
|
@if (lightness($color) > 50) { |
||||||
|
@return $white; // Lighter backgorund, return dark color |
||||||
|
} @else { |
||||||
|
@return $black; // Darker background, return light color |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
.header-navbar { |
||||||
|
padding: 0px; |
||||||
|
min-height: $navbar-height; |
||||||
|
font-family: $font-family-monospace; |
||||||
|
transition: 300ms ease all, background 0s; |
||||||
|
z-index: 997; |
||||||
|
|
||||||
|
&.fixed-top { |
||||||
|
left: $menu-expanded-width; |
||||||
|
} |
||||||
|
|
||||||
|
// Apply navbar color as per background |
||||||
|
&[class*='bg-'] { |
||||||
|
.navbar-nav { |
||||||
|
.nav-item { |
||||||
|
> a { |
||||||
|
color: set-navbar-text-color($theme-dark-body-color) !important; |
||||||
|
|
||||||
|
i, |
||||||
|
svg, |
||||||
|
span { |
||||||
|
color: set-navbar-text-color($theme-dark-body-color) !important; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
.dropdown-menu { |
||||||
|
i, |
||||||
|
svg { |
||||||
|
color: inherit !important; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
.search-input { |
||||||
|
.input, |
||||||
|
.search-list .auto-suggestion span { |
||||||
|
color: $body-color !important; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
//* Navbar modifiers |
||||||
|
//*------------------------ |
||||||
|
|
||||||
|
// floating nav |
||||||
|
&.floating-nav { |
||||||
|
position: fixed; |
||||||
|
right: 0; |
||||||
|
margin: #{$floating-nav-margin} #{$content-padding} 0; |
||||||
|
width: calc( |
||||||
|
100vw - (100vw - 100%) - calc(#{$content-padding} * 2) - #{$menu-expanded-width} |
||||||
|
); |
||||||
|
border-radius: $card-border-radius; |
||||||
|
z-index: 12; |
||||||
|
} |
||||||
|
|
||||||
|
&.floating-nav2 { |
||||||
|
position: fixed; |
||||||
|
right: 0; |
||||||
|
margin: #{$floating-nav-margin} #{$content-padding} 0; |
||||||
|
width: calc(100vw - (100vw - 100%) - calc(#{$content-padding} * 2)); |
||||||
|
border-radius: $card-border-radius; |
||||||
|
z-index: 12; |
||||||
|
} |
||||||
|
|
||||||
|
// static nav |
||||||
|
&.navbar-static-top { |
||||||
|
top: 0; |
||||||
|
right: 0; |
||||||
|
left: $menu-expanded-width; |
||||||
|
width: calc(100vw - (100vw - 100%) - #{$sidebar-width}); |
||||||
|
background: transparent; |
||||||
|
box-shadow: none !important; // remove this if removing "menu-shadow" class |
||||||
|
} |
||||||
|
|
||||||
|
// add border to navbar |
||||||
|
&.navbar-border { |
||||||
|
border-bottom: 1px solid $border-color; |
||||||
|
} |
||||||
|
|
||||||
|
// add shadow to navbar |
||||||
|
&.navbar-shadow { |
||||||
|
box-shadow: $box-shadow; |
||||||
|
} |
||||||
|
|
||||||
|
&.navbar-dark.navbar-border { |
||||||
|
border-bottom: 1px solid $theme-dark-border-color; |
||||||
|
} |
||||||
|
|
||||||
|
// Hide navbar dropdown arrow |
||||||
|
&:not(.navbar-horizontal) { |
||||||
|
.nav-link { |
||||||
|
&.dropdown-toggle::after { |
||||||
|
display: none; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
//* Navbar modifiers |
||||||
|
//*------------------------ |
||||||
|
|
||||||
|
.navbar-container { |
||||||
|
padding: 0.8rem 1rem; |
||||||
|
// Added more horizontal padding above small screen |
||||||
|
@include media-breakpoint-up(sm) { |
||||||
|
padding: 0.8rem 1.4rem; |
||||||
|
} |
||||||
|
flex-basis: 100%; |
||||||
|
transition: 300ms ease all; |
||||||
|
margin-left: 0; |
||||||
|
|
||||||
|
// Navbar bookmark primary color on hover |
||||||
|
.bookmark-wrapper { |
||||||
|
// for bookmark z-index |
||||||
|
.bookmark-input { |
||||||
|
z-index: 1; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// Language dd style |
||||||
|
.dropdown-language { |
||||||
|
.selected-language { |
||||||
|
font-weight: 500; |
||||||
|
} |
||||||
|
.nav-link { |
||||||
|
.flag-icon { |
||||||
|
margin-right: 0.4rem; |
||||||
|
} |
||||||
|
} |
||||||
|
.dropdown-menu .dropdown-item { |
||||||
|
.flag-icon { |
||||||
|
margin-right: 0.4rem; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
ul.navbar-nav { |
||||||
|
li { |
||||||
|
line-height: 1.5; |
||||||
|
&.dropdown { |
||||||
|
.dropdown-menu { |
||||||
|
.vertical-layout & { |
||||||
|
top: 41px !important; // Apply navbar dd position on vertical layouts only (Not for horizontal layout due to hover out issue) |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
&.dropdown-language { |
||||||
|
.dropdown-menu.dropdown-menu-right { |
||||||
|
right: -2px; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// Cart & Notification badge |
||||||
|
&.dropdown-cart, |
||||||
|
&.dropdown-notification { |
||||||
|
.badge { |
||||||
|
&.badge-up { |
||||||
|
right: -3px; |
||||||
|
} |
||||||
|
} |
||||||
|
.dropdown-menu.dropdown-menu-right { |
||||||
|
right: -2px; |
||||||
|
padding: 0; |
||||||
|
left: inherit; |
||||||
|
&::before { |
||||||
|
background: $primary; |
||||||
|
border-color: $primary; |
||||||
|
} |
||||||
|
} |
||||||
|
.dropdown-menu-header { |
||||||
|
border-top-left-radius: $dropdown-border-radius; |
||||||
|
border-top-right-radius: $dropdown-border-radius; |
||||||
|
.dropdown-header { |
||||||
|
padding: 1.22rem 1.28rem; |
||||||
|
} |
||||||
|
} |
||||||
|
.notification-text { |
||||||
|
margin-bottom: 0.5rem; |
||||||
|
font-size: smaller; |
||||||
|
color: $text-muted; |
||||||
|
} |
||||||
|
.dropdown-menu-footer { |
||||||
|
padding: 1.28rem; |
||||||
|
} |
||||||
|
} |
||||||
|
&.dropdown-notification { |
||||||
|
.media-body { |
||||||
|
.media-heading { |
||||||
|
color: $body-color; |
||||||
|
margin-bottom: 0; |
||||||
|
line-height: 1.2; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// Cart dropdown |
||||||
|
&.dropdown-cart { |
||||||
|
.media { |
||||||
|
position: relative; |
||||||
|
img { |
||||||
|
background: $body-bg; |
||||||
|
} |
||||||
|
&:hover { |
||||||
|
.cart-item-remove { |
||||||
|
visibility: visible; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
.media-heading { |
||||||
|
width: 8rem; |
||||||
|
h6.cart-item-title { |
||||||
|
display: -webkit-box; |
||||||
|
-webkit-line-clamp: 2; |
||||||
|
-webkit-box-orient: vertical; |
||||||
|
overflow: hidden; |
||||||
|
} |
||||||
|
.cart-item-by { |
||||||
|
color: $text-muted; |
||||||
|
display: -webkit-box; |
||||||
|
-webkit-line-clamp: 1; |
||||||
|
-webkit-box-orient: vertical; |
||||||
|
overflow: hidden; |
||||||
|
} |
||||||
|
} |
||||||
|
.media-body { |
||||||
|
display: flex; |
||||||
|
align-items: center; |
||||||
|
justify-content: space-between; |
||||||
|
} |
||||||
|
.cart-item-price { |
||||||
|
margin-bottom: 0; |
||||||
|
width: 5rem; |
||||||
|
text-align: right; |
||||||
|
} |
||||||
|
|
||||||
|
.cart-item-remove { |
||||||
|
position: absolute; |
||||||
|
top: 10px; |
||||||
|
right: 17px; |
||||||
|
width: 14px; |
||||||
|
height: 14px; |
||||||
|
cursor: pointer; |
||||||
|
@include media-breakpoint-up(md) { |
||||||
|
visibility: hidden; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
> a.nav-link { |
||||||
|
color: $body-color; |
||||||
|
padding: 0 0.5rem; |
||||||
|
position: relative; |
||||||
|
} |
||||||
|
|
||||||
|
&.dropdown-user { |
||||||
|
line-height: 1 !important; // Set due to custom 2 line component in navbar |
||||||
|
.dropdown-menu { |
||||||
|
width: 12rem; |
||||||
|
margin-top: 10px; |
||||||
|
i, |
||||||
|
svg { |
||||||
|
height: 16px; |
||||||
|
width: 16px; |
||||||
|
font-size: 16px; |
||||||
|
vertical-align: top; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// Logged in user dropdown styles |
||||||
|
a.dropdown-user-link { |
||||||
|
display: flex; |
||||||
|
align-items: center; |
||||||
|
|
||||||
|
.user-name { |
||||||
|
display: inline-block; |
||||||
|
margin-bottom: 0.435rem; |
||||||
|
margin-left: 0.2rem; |
||||||
|
} |
||||||
|
|
||||||
|
.user-status { |
||||||
|
font-size: smaller; |
||||||
|
} |
||||||
|
|
||||||
|
img { |
||||||
|
box-shadow: 0 4px 8px 0 rgba($black, 0.12), |
||||||
|
0 2px 4px 0 rgba($black, 0.08); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// navbar toggle menu size (display below lg) |
||||||
|
a.menu-toggle { |
||||||
|
i, |
||||||
|
svg { |
||||||
|
height: 1.6rem; |
||||||
|
width: 1.6rem; |
||||||
|
font-size: 1.6rem; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
a.dropdown-user-link { |
||||||
|
.user-nav { |
||||||
|
display: flex; |
||||||
|
flex-direction: column; |
||||||
|
align-items: flex-end; |
||||||
|
float: left; |
||||||
|
margin-right: $spacer - 0.2; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
div.input-group { |
||||||
|
padding: 0.7rem 1rem; |
||||||
|
} |
||||||
|
|
||||||
|
i, |
||||||
|
svg { |
||||||
|
&.ficon { |
||||||
|
height: 1.5rem; |
||||||
|
width: 1.5rem; |
||||||
|
font-size: 1.5rem; |
||||||
|
color: $body-color; |
||||||
|
|
||||||
|
&:hover { |
||||||
|
color: $primary; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
.media-list { |
||||||
|
max-height: 25rem; |
||||||
|
} |
||||||
|
|
||||||
|
.scrollable-container { |
||||||
|
position: relative; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
//Navbar notification css |
||||||
|
.dropdown-menu-media { |
||||||
|
width: 30rem; |
||||||
|
|
||||||
|
.dropdown-menu-header { |
||||||
|
border-bottom: 1px solid $border-color; |
||||||
|
} |
||||||
|
|
||||||
|
.media-list { |
||||||
|
.media { |
||||||
|
padding: 0.9rem 1.28rem; |
||||||
|
border: none; |
||||||
|
border-bottom: 1px solid $border-color; |
||||||
|
|
||||||
|
&:hover { |
||||||
|
background: $body-bg; |
||||||
|
} |
||||||
|
|
||||||
|
.media-meta { |
||||||
|
color: $body-color; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
a:last-of-type { |
||||||
|
.media { |
||||||
|
border-bottom: none; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
.dropdown-menu-footer { |
||||||
|
border-top: 1px solid $border-color; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// Navbar shadow on scroll |
||||||
|
.header-navbar-shadow { |
||||||
|
display: none; |
||||||
|
} |
||||||
|
|
||||||
|
// Floating Navbar |
||||||
|
.navbar-floating { |
||||||
|
// Floating nav should have same padding across all screen |
||||||
|
.navbar-container { |
||||||
|
padding: 0.8rem 1rem; |
||||||
|
} |
||||||
|
.header-navbar-shadow { |
||||||
|
display: block; |
||||||
|
background: linear-gradient( |
||||||
|
180deg, |
||||||
|
hsla(0, 0%, 97.3%, 0.95) 44%, |
||||||
|
hsla(0, 0%, 97.3%, 0.46) 73%, |
||||||
|
hsla(0, 0%, 100%, 0) |
||||||
|
); |
||||||
|
padding-top: 2.2rem; |
||||||
|
background-repeat: repeat; |
||||||
|
width: 100%; |
||||||
|
height: 102px; |
||||||
|
position: fixed; |
||||||
|
top: 0; |
||||||
|
left: 0; |
||||||
|
z-index: 11; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// Navbar colors |
||||||
|
.navbar-light { |
||||||
|
background: $white; |
||||||
|
|
||||||
|
&.navbar-horizontal { |
||||||
|
background: $white; |
||||||
|
} |
||||||
|
|
||||||
|
.navbar-nav { |
||||||
|
.active { |
||||||
|
&.nav-link { |
||||||
|
background-color: rgba($black, 0.03); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
.disabled { |
||||||
|
&.nav-link { |
||||||
|
color: $nav-link-disabled-color; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
.navbar-dark { |
||||||
|
background: $gray-600; |
||||||
|
|
||||||
|
.navbar-brand { |
||||||
|
color: $white !important; |
||||||
|
} |
||||||
|
|
||||||
|
&.navbar-horizontal { |
||||||
|
background: $gray-600; |
||||||
|
} |
||||||
|
|
||||||
|
.nav-search { |
||||||
|
.form-control, |
||||||
|
.btn-secondary { |
||||||
|
color: $white; |
||||||
|
background: $gray-600; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
.navbar-nav { |
||||||
|
li { |
||||||
|
line-height: 1; |
||||||
|
} |
||||||
|
|
||||||
|
.active { |
||||||
|
&.nav-link { |
||||||
|
background-color: rgba($white, 0.05); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
.disabled { |
||||||
|
&.nav-link { |
||||||
|
color: $gray-300; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// Media queries for device support |
||||||
|
// ========================================= |
||||||
|
@include media-breakpoint-down(sm) { |
||||||
|
.header-navbar { |
||||||
|
// generic navbar dropdown specific |
||||||
|
.navbar-nav { |
||||||
|
.show { |
||||||
|
position: static; |
||||||
|
} |
||||||
|
|
||||||
|
.open-navbar-container { |
||||||
|
padding-top: 0.625rem; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
.navbar-container { |
||||||
|
.show { |
||||||
|
.dropdown-menu { |
||||||
|
right: 0; |
||||||
|
left: 0 !important; |
||||||
|
float: none; |
||||||
|
width: auto !important; |
||||||
|
margin-top: 0; |
||||||
|
overflow: hidden; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
.dropdown-user { |
||||||
|
.dropdown-menu-right { |
||||||
|
right: 0 !important; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
ul.navbar-nav { |
||||||
|
li { |
||||||
|
.dropdown-toggle::after { |
||||||
|
margin-right: 0; |
||||||
|
margin-left: -2px; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// dark navbar |
||||||
|
.navbar-dark { |
||||||
|
.navbar-header { |
||||||
|
.navbar-nav { |
||||||
|
.nav-link { |
||||||
|
color: $white; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
.navbar-container { |
||||||
|
.navbar-nav { |
||||||
|
.nav-link { |
||||||
|
color: $gray-600; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// light navbar |
||||||
|
.navbar-light { |
||||||
|
.navbar-header { |
||||||
|
.navbar-nav { |
||||||
|
.nav-link { |
||||||
|
color: $gray-600; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
.navbar-container { |
||||||
|
.navbar-nav { |
||||||
|
.nav-link { |
||||||
|
color: $gray-600; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// For Medium and down: iPad support for navbr |
||||||
|
|
||||||
|
// navbar static top |
||||||
|
@include media-breakpoint-down(lg) { |
||||||
|
.header-navbar { |
||||||
|
// floating nav width |
||||||
|
&.floating-nav { |
||||||
|
width: calc(100vw - (100vw - 100%) - calc(#{$content-padding} * 2)); |
||||||
|
} |
||||||
|
&.navbar-static-top { |
||||||
|
left: 0; |
||||||
|
width: 100%; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
//For responsive sub nav |
||||||
|
@mixin responsive_sub_nav { |
||||||
|
.header-navbar { |
||||||
|
.navbar-nav { |
||||||
|
margin: 0; |
||||||
|
flex-flow: row wrap; |
||||||
|
|
||||||
|
.dropdown-menu { |
||||||
|
position: absolute; |
||||||
|
} |
||||||
|
|
||||||
|
.nav-item { |
||||||
|
float: left; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@include media-breakpoint-down(md) { |
||||||
|
@include responsive_sub_nav; |
||||||
|
} |
||||||
|
@media (max-width: 767px) { |
||||||
|
@include responsive_sub_nav; |
||||||
|
} |
||||||
|
|
||||||
|
@include media-breakpoint-down(xs) { |
||||||
|
.header-navbar { |
||||||
|
&.floating-nav { |
||||||
|
width: calc( |
||||||
|
100vw - (100vw - 100%) - calc(#{$content-padding} + 0.4rem) |
||||||
|
) !important; // SM screen calc as per updated spacings |
||||||
|
margin-left: 1rem; |
||||||
|
margin-right: 1.2rem; |
||||||
|
} |
||||||
|
|
||||||
|
.navbar-container ul.navbar-nav li .selected-language { |
||||||
|
display: none; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/* ----------- iPhone 5, 5S iPhone 6----------- */ |
||||||
|
|
||||||
|
// Set dropdown height as per the screen size |
||||||
|
@mixin extend_mobile_specific($menu_height) { |
||||||
|
.header-navbar { |
||||||
|
.navbar-container { |
||||||
|
.show { |
||||||
|
.dropdown-menu { |
||||||
|
max-height: $menu_height; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/* Landscape */ |
||||||
|
|
||||||
|
@media only screen and (min-device-width: 26.78em) and (max-device-width: 47.64em) and (-webkit-min-device-pixel-ratio: 2) and (orientation: landscape) { |
||||||
|
@include extend_mobile_specific(180px); |
||||||
|
} |
||||||
|
|
||||||
|
/* ----------- iPhone 6+ ----------- */ |
||||||
|
|
||||||
|
/* Landscape */ |
||||||
|
|
||||||
|
@media only screen and (min-device-width: 29.57em) and (max-device-width: 52.57em) and (-webkit-min-device-pixel-ratio: 3) and (orientation: landscape) { |
||||||
|
@include extend_mobile_specific(280px); |
||||||
|
} |
||||||
|
|
||||||
|
// for width of navbar in fixed-top |
||||||
|
@media (max-width: 1201px) { |
||||||
|
.header-navbar { |
||||||
|
&.fixed-top { |
||||||
|
left: 0; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
.horizontal-layout { |
||||||
|
.header-navbar { |
||||||
|
.navbar-container { |
||||||
|
padding-left: 0.8rem; |
||||||
|
padding-right: 0.8rem; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@media (max-width: 1199px) { |
||||||
|
.header-navbar { |
||||||
|
.navbar-container { |
||||||
|
ul.navbar-nav li a.dropdown-user-link .user-name { |
||||||
|
margin-bottom: 0; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,307 @@ |
|||||||
|
// Pagination |
||||||
|
|
||||||
|
// default look for page item, first and last item |
||||||
|
|
||||||
|
.page-item { |
||||||
|
border-radius: 5rem; |
||||||
|
|
||||||
|
&:not(.prev-item), |
||||||
|
&:not(.next-item), |
||||||
|
&:not(.first), |
||||||
|
&:not(.last), |
||||||
|
&:not(.active) { |
||||||
|
.page-link { |
||||||
|
line-height: 1.3; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
.page-link { |
||||||
|
display: flex; |
||||||
|
align-items: center; |
||||||
|
justify-content: center; |
||||||
|
} |
||||||
|
&.previous, |
||||||
|
&.prev, |
||||||
|
&.next, |
||||||
|
&.first, |
||||||
|
&.last { |
||||||
|
.page-link { |
||||||
|
width: auto; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
&.prev-item, |
||||||
|
&.next-item { |
||||||
|
.page-link { |
||||||
|
transition: all 0.2s ease-out; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// prev and next item separated styles |
||||||
|
&.prev-item { |
||||||
|
margin-right: 0.3571rem; |
||||||
|
|
||||||
|
.page-link { |
||||||
|
border-radius: 50%; |
||||||
|
|
||||||
|
&:before { |
||||||
|
background-image: url(str-replace(str-replace($chevron-left, 'currentColor', $pagination-color), '#', '%23')); |
||||||
|
background-repeat: no-repeat; |
||||||
|
background-position: center; |
||||||
|
background-size: 14px; |
||||||
|
color: $body-color; |
||||||
|
width: 8px; |
||||||
|
height: 18px; |
||||||
|
content: ''; |
||||||
|
} |
||||||
|
|
||||||
|
&:hover { |
||||||
|
background: $pagination-hover-bg; |
||||||
|
color: $pagination-hover-color; |
||||||
|
} |
||||||
|
&:active, |
||||||
|
&:hover { |
||||||
|
background-color: $primary !important; |
||||||
|
&:before { |
||||||
|
background-image: url(str-replace(str-replace($chevron-left, 'currentColor', $white), '#', '%23')) !important; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
&.disabled { |
||||||
|
.page-link { |
||||||
|
&:before { |
||||||
|
background-image: url(str-replace( |
||||||
|
str-replace($chevron-left, 'currentColor', $pagination-disabled-color), |
||||||
|
'#', |
||||||
|
'%23' |
||||||
|
)); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
& ~ .page-item:nth-child(2) { |
||||||
|
border-top-left-radius: 5rem; |
||||||
|
border-bottom-left-radius: 5rem; |
||||||
|
.page-link { |
||||||
|
border-top-left-radius: 5rem !important; |
||||||
|
border-bottom-left-radius: 5rem !important; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
& ~ .page-item:nth-last-child(2) { |
||||||
|
border-top-right-radius: 5rem; |
||||||
|
border-bottom-right-radius: 5rem; |
||||||
|
.page-link { |
||||||
|
border-top-right-radius: 5rem !important; |
||||||
|
border-bottom-right-radius: 5rem !important; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
&.next-item { |
||||||
|
margin-left: 0.3571rem; |
||||||
|
|
||||||
|
.page-link { |
||||||
|
border-radius: 50%; |
||||||
|
|
||||||
|
&:after { |
||||||
|
background-image: url(str-replace(str-replace($chevron-right, 'currentColor', $pagination-color), '#', '%23')); |
||||||
|
background-repeat: no-repeat; |
||||||
|
background-position: center; |
||||||
|
background-size: 14px; |
||||||
|
width: 8px; |
||||||
|
height: 18px; |
||||||
|
content: ''; |
||||||
|
} |
||||||
|
|
||||||
|
&:hover { |
||||||
|
background: $pagination-hover-bg; |
||||||
|
color: $pagination-hover-color; |
||||||
|
} |
||||||
|
&:active, |
||||||
|
&:hover { |
||||||
|
background-color: $primary !important; |
||||||
|
&:after { |
||||||
|
background-image: url(str-replace( |
||||||
|
str-replace($chevron-right, 'currentColor', $white), |
||||||
|
'#', |
||||||
|
'%23' |
||||||
|
)) !important; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
&.disabled { |
||||||
|
.page-link { |
||||||
|
&:after { |
||||||
|
background-image: url(str-replace( |
||||||
|
str-replace($chevron-right, 'currentColor', $pagination-disabled-color), |
||||||
|
'#', |
||||||
|
'%23' |
||||||
|
)); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// prev and next style |
||||||
|
&.prev, |
||||||
|
&.previous { |
||||||
|
.page-link { |
||||||
|
&:before { |
||||||
|
background-image: url(str-replace(str-replace($chevron-left, 'currentColor', $pagination-color), '#', '%23')); |
||||||
|
background-repeat: no-repeat; |
||||||
|
background-position: center; |
||||||
|
background-size: 14px; |
||||||
|
color: $body-color; |
||||||
|
width: 12px; |
||||||
|
height: 18px; |
||||||
|
content: ''; |
||||||
|
} |
||||||
|
// &:active, |
||||||
|
&:hover { |
||||||
|
&:before { |
||||||
|
background-image: url(str-replace( |
||||||
|
str-replace($chevron-left, 'currentColor', $pagination-active-color), |
||||||
|
'#', |
||||||
|
'%23' |
||||||
|
)) !important; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
&.disabled { |
||||||
|
.page-link { |
||||||
|
&:before { |
||||||
|
background-image: url(str-replace( |
||||||
|
str-replace($chevron-left, 'currentColor', $pagination-disabled-color), |
||||||
|
'#', |
||||||
|
'%23' |
||||||
|
)); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
&.next { |
||||||
|
.page-link { |
||||||
|
&:after { |
||||||
|
background-image: url(str-replace(str-replace($chevron-right, 'currentColor', $pagination-color), '#', '%23')); |
||||||
|
background-repeat: no-repeat; |
||||||
|
background-position: center; |
||||||
|
background-size: 14px; |
||||||
|
color: $body-color; |
||||||
|
width: 12px; |
||||||
|
height: 18px; |
||||||
|
content: ''; |
||||||
|
} |
||||||
|
// &:active, |
||||||
|
&:hover { |
||||||
|
&:after { |
||||||
|
background-image: url(str-replace( |
||||||
|
str-replace($chevron-right, 'currentColor', $primary), |
||||||
|
'#', |
||||||
|
'%23' |
||||||
|
)) !important; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
&.disabled { |
||||||
|
.page-link { |
||||||
|
&:after { |
||||||
|
background-image: url(str-replace( |
||||||
|
str-replace($chevron-right, 'currentColor', $pagination-disabled-color), |
||||||
|
'#', |
||||||
|
'%23' |
||||||
|
)); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
&.disabled { |
||||||
|
.page-link { |
||||||
|
color: $pagination-disabled-color; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// page link customization |
||||||
|
|
||||||
|
.page-link { |
||||||
|
border: none; |
||||||
|
margin: 0; |
||||||
|
margin-left: 0; |
||||||
|
font-size: 1rem; |
||||||
|
min-width: 2.286rem; |
||||||
|
&:focus { |
||||||
|
box-shadow: none; |
||||||
|
} |
||||||
|
|
||||||
|
&:hover { |
||||||
|
color: $primary; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// for active page item |
||||||
|
&.active { |
||||||
|
background-color: $pagination-bg; |
||||||
|
border-radius: 0; |
||||||
|
|
||||||
|
.page-link { |
||||||
|
z-index: 3; |
||||||
|
border-radius: 5rem; |
||||||
|
background-color: $primary; |
||||||
|
color: $white !important; |
||||||
|
font-weight: 600; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// if you don't want separated look |
||||||
|
|
||||||
|
&:first-child:not(.prev-item) { |
||||||
|
&.active { |
||||||
|
border-top-left-radius: 1.428rem; |
||||||
|
border-bottom-left-radius: 1.428rem; |
||||||
|
.page-link { |
||||||
|
border-radius: 5rem; |
||||||
|
} |
||||||
|
} |
||||||
|
.page-link { |
||||||
|
border-top-left-radius: 1.428rem; |
||||||
|
border-bottom-left-radius: 1.428rem; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
&:last-child:not(.next-item) { |
||||||
|
&.active { |
||||||
|
border-top-right-radius: 1.428rem; |
||||||
|
border-bottom-right-radius: 1.428rem; |
||||||
|
.page-link { |
||||||
|
border-radius: 5rem; |
||||||
|
} |
||||||
|
} |
||||||
|
.page-link { |
||||||
|
border-top-right-radius: 1.428rem; |
||||||
|
border-bottom-right-radius: 1.428rem; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// For Pagination Font sizes |
||||||
|
.pagination { |
||||||
|
// For Pagination lg |
||||||
|
&.pagination-lg { |
||||||
|
.page-item { |
||||||
|
.page-link { |
||||||
|
font-size: $pagination-font-size-lg; |
||||||
|
min-width: 2.6rem; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
// For Pagination sm |
||||||
|
&.pagination-sm { |
||||||
|
.page-item { |
||||||
|
.page-link { |
||||||
|
font-size: $pagination-font-size-sm; |
||||||
|
min-width: 2rem; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,45 @@ |
|||||||
|
// Popovers |
||||||
|
|
||||||
|
.popover { |
||||||
|
box-shadow: $popover-box-shadow; |
||||||
|
// popover header style |
||||||
|
.popover-header { |
||||||
|
@include font-size(1.07rem); |
||||||
|
border: 1px solid $popover-header-bg; |
||||||
|
} |
||||||
|
// popover body style |
||||||
|
.popover-body { |
||||||
|
border: 1px solid $popover-border-color; |
||||||
|
border-top-color: $popover-bg; |
||||||
|
border-bottom-left-radius: $popover-border-radius; |
||||||
|
border-bottom-right-radius: $popover-border-radius; |
||||||
|
} |
||||||
|
// popover bottom arrow color like header |
||||||
|
&.bs-popover-bottom { |
||||||
|
.arrow:after { |
||||||
|
border-bottom-color: $popover-header-bg; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
// To set arrow border as we have added border to popover-body and popover-header |
||||||
|
.bs-popover-top { |
||||||
|
> .arrow { |
||||||
|
&::after { |
||||||
|
bottom: $popover-border-width + 1px; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
.bs-popover-right { |
||||||
|
> .arrow { |
||||||
|
&::after { |
||||||
|
left: $popover-border-width + 1px; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
.bs-popover-left { |
||||||
|
> .arrow { |
||||||
|
&::after { |
||||||
|
right: $popover-border-width + 1px; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,20 @@ |
|||||||
|
/*========================================================================================= |
||||||
|
File Name: progress.scss |
||||||
|
Description: Extended bootstrap progress bar scss. |
||||||
|
---------------------------------------------------------------------------------------- |
||||||
|
Item Name: Vuexy - Vuejs, HTML & Laravel Admin Dashboard Template |
||||||
|
Author: PIXINVENT |
||||||
|
Author URL: http://www.themeforest.net/user/pixinvent |
||||||
|
---------------------------------------------------------------------------------------- |
||||||
|
==========================================================================================*/ |
||||||
|
|
||||||
|
.progress { |
||||||
|
// border radius to set for stacked bars |
||||||
|
.progress-bar + .progress-bar:not(:last-child) { |
||||||
|
border-radius: 0; |
||||||
|
} |
||||||
|
.progress-bar:last-child { |
||||||
|
border-top-right-radius: $progress-border-radius; |
||||||
|
border-bottom-right-radius: $progress-border-radius; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,15 @@ |
|||||||
|
a { |
||||||
|
&:focus { |
||||||
|
outline: none; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
a:not([href]) { |
||||||
|
color: inherit; |
||||||
|
text-decoration: none; |
||||||
|
|
||||||
|
@include hover() { |
||||||
|
color: inherit; |
||||||
|
text-decoration: none; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,122 @@ |
|||||||
|
// ================================================================================================ |
||||||
|
// File Name: tables.scss |
||||||
|
// Description: Tables pages custom scss |
||||||
|
// ---------------------------------------------------------------------------------------------- |
||||||
|
// Item Name: Vuexy - Vuejs, HTML & Laravel Admin Dashboard Template |
||||||
|
// Author: PIXINVENT |
||||||
|
// Author URL: http://www.themeforest.net/user/pixinvent |
||||||
|
// ================================================================================================ |
||||||
|
|
||||||
|
// table-white-space |
||||||
|
.table-white-space { |
||||||
|
th, |
||||||
|
td { |
||||||
|
white-space: nowrap; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// table th, td padding |
||||||
|
.table { |
||||||
|
thead, |
||||||
|
tfoot { |
||||||
|
th { |
||||||
|
vertical-align: top; |
||||||
|
text-transform: uppercase; |
||||||
|
font-size: $table-th-font-size; |
||||||
|
letter-spacing: 0.5px; |
||||||
|
} |
||||||
|
} |
||||||
|
th, |
||||||
|
td { |
||||||
|
padding: $table-cell-padding 2rem; |
||||||
|
vertical-align: middle; |
||||||
|
} |
||||||
|
&.table-sm { |
||||||
|
th, |
||||||
|
td { |
||||||
|
padding: $table-cell-padding-sm 0.5rem; |
||||||
|
&:first-child { |
||||||
|
padding-left: 0.75rem; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
// if we are not using table-light class then also header color should apply |
||||||
|
.table:not(.table-dark):not(.table-light) { |
||||||
|
thead:not(.thead-dark) th, |
||||||
|
tfoot:not(.thead-dark) th { |
||||||
|
background-color: $table-head-bg; |
||||||
|
} |
||||||
|
} |
||||||
|
// table inside card, don't need margin bottom |
||||||
|
.table-hover { |
||||||
|
tbody { |
||||||
|
tr { |
||||||
|
cursor: pointer; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
// Table - hover animation |
||||||
|
.table-hover-animation { |
||||||
|
background-color: $body-bg; |
||||||
|
thead { |
||||||
|
th { |
||||||
|
border-bottom: 0; |
||||||
|
} |
||||||
|
} |
||||||
|
th, |
||||||
|
td { |
||||||
|
border: 0; |
||||||
|
} |
||||||
|
tbody { |
||||||
|
tr { |
||||||
|
transition: all 0.25s ease; |
||||||
|
background-color: $white; |
||||||
|
&:hover { |
||||||
|
transform: translateY(-4px); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// table border radius |
||||||
|
.card .table { |
||||||
|
margin-bottom: 0; |
||||||
|
border-bottom-left-radius: $border-radius; |
||||||
|
border-bottom-right-radius: $border-radius; |
||||||
|
tbody { |
||||||
|
tr:last-child { |
||||||
|
td:first-child { |
||||||
|
border-bottom-left-radius: $border-radius; |
||||||
|
} |
||||||
|
td:last-child { |
||||||
|
border-bottom-right-radius: $border-radius; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// Contexual table inside card radius |
||||||
|
.card { |
||||||
|
table { |
||||||
|
tr[class*='table-']:last-child { |
||||||
|
td:first-child { |
||||||
|
border-bottom-left-radius: $border-radius; |
||||||
|
} |
||||||
|
td:last-child { |
||||||
|
border-bottom-right-radius: $border-radius; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// IE Specific CSS |
||||||
|
@media screen and (-ms-high-contrast: active), (-ms-high-contrast: none) { |
||||||
|
.table-hover-animation { |
||||||
|
tr { |
||||||
|
&:hover { |
||||||
|
border-bottom-color: $table-border-color; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue