Initial import

This commit is contained in:
Flatlogic Bot 2026-05-11 17:18:27 +02:00
commit dbf400f9be
557 changed files with 75788 additions and 0 deletions

1
.env Normal file
View File

@ -0,0 +1 @@
VITE_BACKEND=false

37
.github/workflows/ci.yml vendored Normal file
View File

@ -0,0 +1,37 @@
name: CI
on:
push:
branches:
- master
pull_request:
jobs:
validate:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
node-version: [20.x, 22.x]
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
cache: npm
- name: Install
run: npm ci
- name: Lint
run: npm run lint
- name: Build
run: npm run build
- name: Test
run: npm test

23
.gitignore vendored Normal file
View File

@ -0,0 +1,23 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
# 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*
.idea

21
LICENSE Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2017 FLATLOGIC.COM
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

131
README.md Normal file
View File

@ -0,0 +1,131 @@
# 🚀 Light Blue React - A Free Transparent React Admin Template!
[View Demo](https://flatlogic.com/templates/light-blue-react/demo) | [Download](https://github.com/flatlogic/light-blue-react/archive/refs/heads/master.zip) | [More Templates](https://flatlogic.com/templates) | [Discord Community](https://discord.gg/flatlogic-community) | [Support Forum](https://flatlogic.com/forum)
**Originally a premium product priced at $69+, made available for free in January 2025!** 🎉
Looking for a perfect codebase generator for your Startup? Try [Flatlogic AI Web App Generator](https://flatlogic.com/generator) - our new tool, sort of a template++.
---
## 🎯 Why Light Blue React?
- **Ex-Premium**: This template was previously paid. Enjoy it for free now. 😉
- **Tons of components**: Hundreds of ready-to-use UI elements, charts, and more.
- **Join the Community**: [Flatlogic Discord](https://discord.gg/flatlogic-community) is where the action happens.
- **Free Node.js Backend**: Pair it up with [this backend](https://github.com/flatlogic/nodejs-backend) to go full-stack.
---
## 🚀 Quick Start
1. **Clone the repo**
```bash
git clone https://github.com/flatlogic/light-blue-react.git
cd light-blue-react
```
2. **Install dependencies**
```bash
npm install --force
```
This repository is maintained with npm lockfile (`package-lock.json`).
Peer override is currently required because several legacy demo dependencies still declare React 18 peer ranges.
3. **Run the app**
```bash
npm run dev
```
Navigate to http://localhost:3000/.
4. **Backend Support**
```bash
npm run start:backend
```
5. **Build for production**
```bash
npm run build
```
6. **Preview production build locally**
```bash
npm run preview
```
7. **Run tests**
```bash
npm test
```
---
## 🧩 Features
- Easily customizable styling & themes
- Over 30 Unique Pages
- Fully Responsive
- React 19
- React Router 7
- Bootstrap 5
- Developer-Oriented Dashboard
- Fully Documented Codebase
---
## 🛠 Built With
- React 19
- Bootstrap 5
- Node.js
- Vite 7 + SWC
- Vitest
- SASS
- JavaScript (ES6)
Node engine target in `package.json`: `^20.19.0 || >=22.12.0`.
---
## 📦 Components
- UI Elements (Badge, Card, Carousel, Modal, etc.)
- Charts (Flot, Morris, Rickshaw, Sparkline, Easy Pie Charts)
- Forms (Validation, Wizard, Elements)
- Dashboards (Analytics, Visits)
- Pages (Profile, E-commerce, Calendar, Chat, Error)
- Maps (Google, Vector)
---
## 🌍 Available Variants
| | **Material** | **Transparent** | **Classic** | **Sofia** | **Flatlogic** |
|---------------|-----------------------------------------------------------|---------------------------------------------------------|-------------------------------------------------------|-----------------------------------------------------|----------------------------------------------------|
| **React** | [React Material Admin](https://github.com/flatlogic/react-material-admin-full) | [Light Blue React](https://github.com/flatlogic/light-blue-react) | [Sing App React](https://github.com/flatlogic/sing-app-react) | [Sofia React](https://github.com/flatlogic/sofia-react) | [One React](https://github.com/flatlogic/one-react) |
| **Angular** | [Angular Material Admin](https://github.com/flatlogic/angular-material-admin-full) | [Light Blue Angular](https://github.com/flatlogic/light-blue-angular) | [Sing App Angular](https://github.com/flatlogic/sing-app-angular) | - | - |
| **Vue** | [Material Vue](https://github.com/flatlogic/material-vue-full) | [Light Blue Vue](https://github.com/flatlogic/light-blue-vue) | [Sing App Vue](https://github.com/flatlogic/sing-app-vue) | - | - |
| **Bootstrap** | - | [Light Blue HTML5](https://github.com/flatlogic/light-blue-html5) | [Sing App HTML5](https://github.com/flatlogic/sing-app-html5) | - | [One Bootstrap](https://github.com/flatlogic/one-bootstrap-template-full) |
Additionally, these templates are tailored for specific business needs:
- [E-Commerce Frontend (React)](https://github.com/flatlogic/ecommerce-frontend) - A complete e-commerce solution.
- [Bookkeeper UI (React)](https://github.com/flatlogic/bookkeeper-ui) - Accounting dashboard for finance management.
- [User Management Template (React)](https://github.com/flatlogic/user-management-template) - User authentication and management.
---
## 👨‍💻 How to Contribute
- **Star this repo ⭐** - show some love.
- **Report bugs** - but be nice.
- **Join the [Discord](<insert-discord-invite-link>)** - meet fellow devs.
---
## 🔥 About Flatlogic
[Flatlogic AI Software Engineer](https://flatlogic.com/ai-software-development-agent) builds modern business software so you don't have to. Our AI Software Development Agent helps you generate, deploy, and maintain enterprise applications with minimal effort.
---
## 📜 License
This template is free to use. Modify it, break it, make it your own. Just dont try to sell it back to us. 😎
---
> **Questions or feedback?**
> Join our [Flatlogic Community Discord](https://discord.gg/flatlogic-community) or visit our [support forum](https://flatlogic.com/forum). We might even reply!

334
changelog.md Normal file
View File

@ -0,0 +1,334 @@
# Changelog
## [Unreleased]
## [8.3.3] - 2026-02-23
- Dependency and runtime cleanup:
- removed Vite Node polyfill plugin and legacy browserify/polyfill packages (`assert`, `crypto-browserify`, `os-browserify`, `process`, `stream-browserify`, `stream-http`, `url`, `vm-browserify`);
- removed direct `lodash` usage from app code paths and replaced it with local utility helpers in form/user formatters;
- pinned transitive `lodash` to a safe version via npm override (`^4.17.23`).
- Lockfile update:
- added `yarn.lock` for Yarn install parity while keeping npm lockfile in place.
## [8.3.2] - 2026-02-23
- Phase 1 modernization baseline fixes:
- fixed dead fallback redirect in app shell (`/app/main/visits` -> `/app/main/dashboard`);
- hardened `AuthRoute` against missing `location.state`;
- normalized login/register/forgot links to absolute auth routes;
- replaced obsolete layout test with route-guard smoke tests;
- removed conflicting project-level `babel.config.js` to align with CRA toolchain.
- Tooling baseline updates:
- added explicit `ajv@^8.18.0` dev dependency to fix webpack/schema-utils `ajv` resolution during build;
- documented working install path (`npm install --force`) in README.
- Phase 2 modernization updates:
- migrated build/dev/preview workflow to Vite + SWC (`vite.config.js`, root `index.html`);
- removed CRA/rewired build overrides (`config-overrides.js`, `public/index.html`, `react-app-rewired`, `react-scripts`);
- migrated test runner to Vitest and retained route-guard smoke coverage;
- migrated runtime env handling to Vite-compatible app env bridge (`VITE_BACKEND` + `__APP_ENV__`);
- kept build output compatibility (`build/`) and added Node memory guard for large production bundle builds;
- standardized lockfile strategy to npm (`package-lock.json`).
- Dependency refresh batch 1:
- low-risk update: `bootstrap` upgraded within major (`5.2.3` -> `5.3.8`);
- major update block A: `axios` (`0.27.2` -> `1.13.5`), `jsonwebtoken` (`8.5.1` -> `9.0.3`), `cross-env` (`7.0.3` -> `10.1.0`);
- adjusted SCSS override to keep build compatibility with Bootstrap 5.3 variable changes.
- Dependency refresh batch 2:
- updated `react-slick` (`0.30.3` -> `0.31.0`), `showdown` (`1.9.1` -> `2.1.0`), and `uuid` (`8.3.2` -> `13.0.0`);
- fixed `redux-thunk` import usage for v3 named export (`ReduxThunk` -> `thunk`) to restore production build compatibility.
- Dependency refresh batch 3:
- updated form/data libs: `formik` (`1.5.8` -> `2.4.9`), `yup` (`0.32.11` -> `1.7.1`), `react-toastify` (`6.2.0` -> `11.0.5`), `react-select` (`3.2.0` -> `5.10.2`), `filesize` (`6.4.0` -> `11.0.13`);
- updated utility libs: `formsy-react` (`0.19.5` -> `2.3.2`) and `styled-components` (`5.3.11` -> `6.3.11`).
- Dependency refresh batch 4:
- updated UI/demo libs: `react-dropzone` (`11.7.1` -> `15.0.0`), `react-autosize-textarea` (`5.0.1` -> `7.1.0`), `react-syntax-highlighter` (`13.5.3` -> `16.1.0`), `react-animate-height` (`2.1.2` -> `3.2.3`), `rc-slider` (`9.7.5` -> `11.1.9`), `react-bootstrap-table-next` (`3.3.5` -> `4.0.3`), `react-bootstrap-table2-toolkit` (`1.4.2` -> `2.1.3`);
- migrated removed `rc-slider` tooltip helper API usage to v11-compatible slider usage in documentation/forms pages.
- Dependency refresh batch 5:
- updated chart libs: `highcharts` (`10.3.3` -> `12.5.0`), `apexcharts` (`3.54.1` -> `5.6.0`), `react-apexcharts` (`1.9.0` -> `2.0.1`);
- updated calendar stack to `@fullcalendar/*` `6.1.20` and adapted calendar config for v6 (`initialView`, list view target `listWeek`, removed deprecated plugin CSS imports).
- Dependency refresh batch 6:
- removed React-16/17-locked dependencies: `connected-react-router`, `react-bootstrap-table-next`, `react-bootstrap-table2-toolkit`, `react-bootstrap-table2-paginator`, `react-google-maps`, `react-images`, `react-maskedinput`, `react-mde`, `react-shuffle`, `react-sortable-hoc`, `react-sortable-tree`, `react-table`;
- replaced dependency-driven implementations with local/runtime-safe equivalents:
- custom navigation action boundary + shared history singleton (no `connected-react-router`);
- native/Reactstrap tables in users/management/dynamic pages (search + pagination preserved);
- iframe-based map component for maps/timeline pages;
- modal-based gallery image viewer;
- local masked input and auto-resize textarea components;
- local markdown editor (write/preview with Showdown);
- native drag-and-drop sortable list implementation for list groups demo;
- removed stale third-party CSS imports tied to deleted packages.
- Dependency refresh batch 7:
- migrated router runtime to `react-router-dom` v7 (`Routes`/`Route`/`Navigate`) across app shell, main layout, and documentation layout;
- removed deprecated router dependencies: `react-router`, `history`, `react-router-hash-link`;
- replaced route guard implementation (`AdminRoute`, `UserRoute`, `AuthRoute`) with v7-compatible wrapper components and refreshed route smoke tests;
- introduced local `withRouter` bridge (`src/components/withRouter.js`) to keep class-component routes working during phased hooks migration;
- replaced hash-link usage in docs scrollspy with `react-router-dom` `Link`.
- Dependency refresh batch 8:
- upgraded framework/tooling stack: `react`/`react-dom` (`18.3.1` -> `19.2.4`), `eslint` (`9.39.x` -> `10.0.1`);
- upgraded chart/sortable stack: `echarts` (`4.9.0` -> `6.0.0`), `echarts-for-react` (`2.0.16` -> `3.0.6`), `react-sortablejs` (`1.5.1` -> `6.1.4`);
- removed obsolete CRA-era dependencies no longer used under Vite: `react-app-polyfill`, `react-dev-utils`, `sass-loader`;
- migrated ECharts imports to modular `echarts/core` registration compatible with ECharts 6.
- Phase 5 legacy cleanup batch:
- migrated app shell entry and docs shell from `class`/`connect`/`withRouter` to hooks (`App`, `DocumentationLayout`, `DocumentationHeader`, `DocumentationSidebar`);
- completed migration away from `react-redux` `connect(...)` HOC to hooks across app-level screens/components;
- converted all header/sidebar icon components to functional React components;
- migrated ecommerce pages/components (`Products`, `Product`, `ProductCard`) to hooks and removed router HOC usage;
- migrated ecommerce management flows (`Management`, `ProductEdit`) to hooks and `useNavigate`/`useLocation` adapter for existing product thunks;
- migrated legacy auth pages (`/pages/login`, `/pages/register`) and users form page to hooks-based implementation;
- migrated users view and rickshaw-based widgets/charts (`UsersViewItem`, `ChangesChart`, `RealtimeTraffic`, dashboard `Rickshaw`) away from `connect` classes;
- replaced sidebar `LinksGroup` HOC routing dependency with native `useLocation` hook and removed obsolete local `withRouter` bridge.
- Phase 4 state modernization:
- moved auth/users side effects to reusable service layer (`src/services/authService.js`, `src/services/usersService.js`);
- migrated users auth-domain thunks to `async/await` with safer shared error-message handling;
- consolidated registration state ownership in `auth` reducer and removed duplicated legacy `register` reducer/actions;
- cleaned users state compatibility fields (`findLoading`/`loading`, list modal/delete metadata) and removed stale empty `dashboard` reducer.
- Phase 5 progress:
- removed deprecated lifecycle methods from source components (`componentWillMount`, `componentWillReceiveProps`);
- migrated users route-level pages (`UsersListPage`, `UsersViewPage`, `ChangePasswordFormPage`) from class components to hooks-based functional components;
- migrated auth route-level pages (`Login`, `Register`, `Forgot`, `Reset`, `Verify`) from class components to hooks-based functional components;
- migrated app shell components (`Layout`, `Header`, `Sidebar`) from class components to hooks-based functional components.
- Phase 6 quality hardening:
- introduced repository lint gate with ESLint flat config and `npm run lint` command;
- added GitHub Actions CI workflow (`.github/workflows/ci.yml`) for `npm ci`, `npm run lint`, `npm run build`, and `npm test`.
- Dependency cleanup and release docs:
- removed unused direct dependencies from runtime manifest: `buffer`, `https-browserify`, `jsonwebtoken`, `md5`, `rc-hammerjs`;
- removed `yarn.lock` to keep npm as the single package manager lock source;
- added migration and release docs (`docs/migration-notes.md`, `docs/adr/0001-routing-and-runtime-baseline.md`, `docs/release-checklist.md`, `docs/rollback-recovery.md`).
- Runtime/tooling compatibility:
- aligned Node engine range to `^20.19.0 || >=22.12.0` to support current Node 22 environments and Vite 7 requirements.
- React 19 is active; some legacy demo dependencies still declare React 18 peer ranges, so install currently uses npm peer override behavior (`npm install --force`) until those packages are replaced.
## [8.3.1] - 26.11.2024
- Update dependencies
## [8.3.0] - 05/09/2024
- Added react-scripts version 5 along with webpack version 5 support.
- Added support for node.js version > 20
- Removed old webpack configs.
- Removed unnecessary dev dependencies.
- Replaced deprecated glyphicons-halflings icon library with bootstrap-icons
## [8.2.3] - 21.12.2023
- Update dependencies
## [8.2.2] - 18.05.2023
- Update dependencies
- Update react version
- Corrected minor errors
## [8.2.1] - 01.07.2022
- UI Adjust
## [8.2.0] - 17.06.2022
- Updated Bootstrap/Reactstrap
- Add theme swicther
- Updated dependencies
## [8.1.6] - 13.05.2021
- Updated blocks position in Typography, Form Validations, LB Packages,
- Products Grid: Customize dropdowns in E-Commerce
- Alerts: Customize alerts notifications
- Dashboard: Fixed position pop-up alert in header
- Add function LoginOut in Login Page,
- Following dependencies and devDependencies was updated to the recent versions
###Dependencies:
"@fullcalendar/core": "5.3.0" -> "5.6.0",
"@fullcalendar/daygrid": "5.3.0" -> "5.6.0",
"@fullcalendar/interaction": "5.3.0" -> "5.6.0",
"@fullcalendar/list": "5.3.0" -> "5.6.0",
"@fullcalendar/react": "5.3.0" -> "5.6.0",
"@fullcalendar/timegrid": "5.3.0" -> "5.6.0",
"axios": "^0.19.2" -> "^0.21.1",
"bootstrap": "4.5.0" -> "4.6.0",`
"classnames": "^2.2.6" -> "^2.3.1",
"connected-react-router": "^6.8.0" -> "6.9.1",
"draft-js": "^0.11.6" -> "^0.11.7",
"echarts-for-react": "^2.0.16",
"file-saver": "^2.0.2" -> "^2.0.5",
"filesize": "^6.1.0" -> "^6.3.0",
"md5": "^2.2.1" -> "^2.3.0",
"rc-slider": "^9.5.1" -> "^9.7.2",
"react": "^16.13.1" -> "^16.14.0",
"react-animate-height": "^2.0.21" -> "^2.0.23",
"react-animated-number": "^0.4.4",
"react-apexcharts": "^1.3.7" -> "^1.3.9",
"react-app-polyfill": "^0.1.3" -> "^0.2.0",
"react-dev-utils": "^6.0.5" -> "^6.1.1",
"react-dom": "^16.5.2" -> "^16.14.0",
"react-draft-wysiwyg": "1.10.12" -> "1.14.7",
"react-dropzone": "^11.2.0" -> "^11.3.2",
"react-mde": "^11.0.0" -> "^11.5.0",
"react-redux": "7.2.0" -> "7.2.4",
"react-router-hash-link": "^2.1.0" -> "^2.4.1",
"react-scrollspy": "^3.4.2" -> "^3.4.3",
"react-select": "^3.1.0" -> "^3.2.0",
"react-slick": "^0.26.1" -> "^0.28.1",
"react-sortable-tree": "^2.7.1" -> "^2.8.0",
"react-toastify": "^6.0.8" -> "^6.2.0",
"react-transition-group": "^4.4.1",
"redux": "^4.0.5" -> "^4.1.0",
"sortablejs": "1.10.2" -> "1.13.0",
"styled-components": "^5.1.1" -> "^5.3.0",
"uuid": "^8.3.0" -> "^8.3.2",
"yup": "^0.29.1" -> "^0.32.9"
###DevDependencies:
"@babel/core": "7.4.4" -> "7.14.0",
"@babel/plugin-proposal-class-properties": "7.4.4" -> "7.13.0",
"@babel/plugin-proposal-optional-chaining": "7.2.0" -> "^7.13.12",
"@svgr/webpack": "4.2.0" ->"4.3.3",
"babel-core": "7.0.0-bridge.0",
"babel-eslint": "10.0.1" -> "10.1.0",
"babel-jest": "24.8.0" -> "24.9.0",
"babel-loader": "8.0.5" -> "8.2.2",
"babel-plugin-named-asset-import": "1.0.0-next.103" -> "1.0.0-next.154",
"babel-preset-react-app": "9.0.0" -> "9.1.2",
"bfj": "6.1.1" -> "6.1.2",
"case-sensitive-paths-webpack-plugin": "2.2.0" -> "2.4.0",
"cross-env": "^7.0.2" -> "^7.0.3",
"dotenv": "8.5.1" -> "8.5.1",
"eslint-plugin-flowtype": "3.8.1" -> "3.13.0",
"eslint-plugin-import": "2.17.2" -> "2.22.1",
"eslint-plugin-jsx-a11y": "6.2.1" -> "6.4.1",
"eslint-plugin-react": "7.13.0" -> "7.23.2",
"eslint-plugin-react-hooks": "1.6.0" -> "1.7.0",
"jest": "24.8.0" -> "24.9.0",
"jest-pnp-resolver": "1.2.1" -> "1.2.2",
"jest-resolve": "24.8.0" -> "24.9.0",
"mini-css-extract-plugin": "0.6.0" -> "0.12.0",
"node-sass": "4.14.0" -> "4.14.1",
"optimize-css-assets-webpack-plugin": "5.0.1" -> "5.0.4",
"pnp-webpack-plugin": "1.4.3" -> "1.6.4",
"postcss-flexbugs-fixes": "4.1.0" -> "4.2.1",
"postcss-preset-env": "6.6.0" -> "6.7.0",
"postcss-safe-parser": "4.0.1" -> "4.0.2",
"resolve": "1.10.1" -> "1.20.0",
"sass-loader": "7.1.0" -> "7.3.1",
"style-loader": "0.23.0" -> "0.23.1",
"terser-webpack-plugin": "1.2.3" -> "1.4.4",
"webpack": "4.31.0" -> "4.44.0",
"webpack-dev-server": "3.3.1" -> "3.11.2",
"webpack-manifest-plugin": "2.0.4" -> "2.2.0",
## [8.1.5]
- Updated documentation
## [8.1.4]
### Updated
- Updated sidebar and header icons
- Updated sidebar and header layout
## [8.1.3]
### Fixed
- Change badge text in the sidebar
- Change alert text in the usermanager/ecommerce
## [8.1.2]
### Fixed bugs and layout issues
- Add new images to Documentation and LB Package pages
- Change progress bars bg color
- Update main colors
- Badges and buttons: fix margins, change font colors
- Dropdowns: change paddings
- Header component: change dropdown hover states
- Charts: fix charts issues
- Fix adaptive and layout issues on pages
- Charts: fix label colors, apex dropdown text
## [8.1.1]
- Added link to flatlogic on login page
## [8.1.0]
- Updated all dependencies, cleaned up dependency tree
## [8.0.5]
- Updated fullcalendar package to v5.3.0
## [8.0.4]
- Add animation to alert in header
- Fix animated classes
- Fix colors in notifications, chart dropdown menu, tables
## [8.0.3]
- Updated line-awesome package
## [8.0.2]
### Fixed bug
- Fixed sidebar caret for Safari
## [8.0.1]
### New Features
- Added sample formik widget
## [8.0.0]
### New Features
- Added brand new Backend
- New tab to mange users
- Social login
- Manage users functionality
- Update password route
- Reset password route
- Upload avatar
- Refactored architecture
## [7.2.0]
### New Features
- Added re-usable breadcrumbs component
## [7.1.2]
### Fixed
- Fixed small calendar events
## [7.1.1]
### Fixed
- Added css fixes
## [7.1.0]
### New Features
- New color scheme
## [7.0.1]
### Fixed
- Fix bugs and css improvements
## [7.0.0]
### Updated
- Removed Jquery from core layout
### New Features
- New charts
## [6.1.0]
### New Features
- Make an api stub for non-backend mode

2568
commonGuide.md Normal file

File diff suppressed because it is too large Load Diff

21
eslint.config.mjs Normal file
View File

@ -0,0 +1,21 @@
export default [
{
ignores: ['build/**', 'node_modules/**'],
linterOptions: {
reportUnusedDisableDirectives: false,
},
},
{
files: ['**/*.js'],
languageOptions: {
ecmaVersion: 'latest',
sourceType: 'module',
parserOptions: {
ecmaFeatures: {
jsx: true,
},
},
},
rules: {},
},
];

93
index.html Normal file
View File

@ -0,0 +1,93 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="referrer" content="no-referrer-when-downgrade" />
<link rel="shortcut icon" href="/favicon.png" />
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
<meta name="theme-color" content="#000000" />
<link rel="manifest" href="/manifest.json" />
<title>Light Blue React Dashboard - Admin Template built with React</title>
<meta
name="description"
content="React Admin Dashboard Template built with Bootstrap, Redux and React Router by Flatlogic. Over 40 unique pages, hundreds of components and theme support."
/>
<meta
name="keywords"
content="react admin, react dashboard, react admin template, react theme, react dashboard template, react dashboard template"
/>
<meta name="author" content="Flatlogic LLC." />
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-36759672-9"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag() {
dataLayer.push(arguments);
}
gtag('js', new Date());
gtag('config', 'UA-36759672-9');
</script>
<script type="text/javascript">
(function (m, e, t, r, i, k, a) {
m[i] = m[i] || function () {
(m[i].a = m[i].a || []).push(arguments);
};
m[i].l = 1 * new Date();
k = e.createElement(t);
a = e.getElementsByTagName(t)[0];
k.async = 1;
k.src = r;
a.parentNode.insertBefore(k, a);
})(window, document, 'script', 'https://cdn.jsdelivr.net/npm/yandex-metrica-watch/tag.js', 'ym');
ym(48020168, 'init', {
id: 48020168,
clickmap: true,
trackLinks: true,
accurateTrackBounce: true,
webvisor: true,
trackHash: true,
ecommerce: 'dataLayer',
});
</script>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<script type="module" src="/src/index.js"></script>
<script type="text/javascript">
window.heap = window.heap || [];
heap.load = function (e, t) {
window.heap.appid = e;
window.heap.config = t = t || {};
var r = t.forceSSL || document.location.protocol === 'https:';
var a = document.createElement('script');
a.type = 'text/javascript';
a.async = true;
a.src = (r ? 'https:' : 'http:') + '//cdn.heapanalytics.com/js/heap-' + e + '.js';
var n = document.getElementsByTagName('script')[0];
n.parentNode.insertBefore(a, n);
var o = function (method) {
return function () {
heap.push([method].concat(Array.prototype.slice.call(arguments, 0)));
};
};
var methods = [
'addEventProperties',
'addUserProperties',
'clearEventProperties',
'identify',
'resetIdentity',
'removeEventProperty',
'setEventProperties',
'track',
'unsetEventProperty',
];
for (var c = 0; c < methods.length; c += 1) {
heap[methods[c]] = o(methods[c]);
}
};
heap.load('3523170338');
</script>
</body>
</html>

7080
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

92
package.json Normal file
View File

@ -0,0 +1,92 @@
{
"name": "light-blue-react",
"version": "8.3.2",
"private": true,
"scripts": {
"dev": "vite",
"start": "vite",
"start:backend": "cross-env VITE_BACKEND=true vite",
"build": "cross-env NODE_OPTIONS=--max-old-space-size=4096 VITE_BACKEND=true vite build",
"preview": "vite preview",
"lint": "eslint src",
"test": "vitest run",
"test:watch": "vitest"
},
"browserslist": [
">0.2%",
"not dead",
"not ie <= 11",
"not op_mini all"
],
"dependencies": {
"@amcharts/amcharts4": "^4.10.35",
"@amcharts/amcharts4-geodata": "^4.1.26",
"@fullcalendar/core": "^6.1.20",
"@fullcalendar/daygrid": "^6.1.20",
"@fullcalendar/interaction": "^6.1.20",
"@fullcalendar/list": "^6.1.20",
"@fullcalendar/react": "^6.1.20",
"@fullcalendar/timegrid": "^6.1.20",
"@popperjs/core": "^2.11.8",
"@reduxjs/toolkit": "^2.11.2",
"animate.css": "4.1.1",
"apexcharts": "^5.6.0",
"awesome-bootstrap-checkbox": "https://github.com/flatlogic/awesome-bootstrap-checkbox#bump-to-bootstrap5",
"axios": "^1.13.5",
"bootstrap": "^5.3.8",
"bootstrap-icons": "^1.11.3",
"classnames": "^2.3.2",
"cross-env": "^10.1.0",
"dayjs": "^1.11.19",
"echarts": "^6.0.0",
"echarts-for-react": "^3.0.6",
"file-saver": "^2.0.5",
"filesize": "^11.0.13",
"font-awesome": "4.7.0",
"formik": "^2.4.9",
"highcharts": "^12.5.0",
"highcharts-react-official": "^3.2.0",
"line-awesome": "^1.3.0",
"rc-slider": "^11.1.9",
"react": "^19.2.4",
"react-animate-height": "^3.2.3",
"react-apexcharts": "^2.0.1",
"react-bootstrap": "^2.10.10",
"react-bootstrap-icons": "^1.11.4",
"react-dom": "^19.2.4",
"react-dropzone": "^15.0.0",
"react-redux": "^9.2.0",
"react-router-dom": "^7.13.0",
"react-select": "^5.10.2",
"react-slick": "^0.31.0",
"react-sortablejs": "^6.1.4",
"react-sparklines": "^1.7.0",
"react-syntax-highlighter": "^16.1.0",
"react-toastify": "^11.0.5",
"react-transition-group": "^4.4.2",
"react-trend": "^1.2.5",
"redux": "^5.0.1",
"sass": "^1.69.5",
"showdown": "^2.1.0",
"sortablejs": "~1.15.4",
"styled-components": "^6.3.11",
"uuid": "^13.0.0",
"yup": "^1.7.1"
},
"engines": {
"node": "^20.19.0 || >=22.12.0"
},
"overrides": {
"lodash": "^4.17.23"
},
"devDependencies": {
"@types/react": "^19.2.2",
"@types/sortablejs": "^1.15.8",
"@vitejs/plugin-react-swc": "^4.2.3",
"ajv": "^8.18.0",
"eslint": "^10.0.1",
"jsdom": "^28.1.0",
"vite": "^7.3.1",
"vitest": "^4.0.18"
}
}

BIN
public/apple-touch-icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

View File

@ -0,0 +1,33 @@
<?php sleep(10) ?>
<h3 class="text-center no-margin animated bounceInDown">Sign up, <del>it's <strong>free</strong></del> and get <strong>$50 now!</strong></h3>
<p class="lead text-muted text-center">
Faith makes it possible to achieve that which man's mind can conceive and believe.
</p>
<form>
<div class="form-group">
<label for="exampleInputEmail1"><i class="fa fa-circle text-warning"></i> &nbsp; Email address</label>
<input type="email" class="form-control input-transparent" id="exampleInputEmail1"
placeholder="Enter email">
</div>
<div class="form-group">
<label for="pswd"><i class="fa fa-circle text-danger"></i> &nbsp; Password</label>
<input class="form-control" id="pswd" type="text" placeholder="Min 8 characters">
</div>
<p>
To make a widget automatically load it's content you just need to set
<strong>data-widgster-autoload</strong> attribute and provide an url.
</p>
<pre><code>data-widgster-load="server/ajax_widget.php"
data-widgster-autoload="true"</code></pre>
<p>
<strong>data-widgster-autoload</strong> may be set to an integer value. If set, for example, to
2000 will refresh widget every 2 seconds.
</p>
<div class="clearfix">
<div class="btn-toolbar float-end">
<button type="submit" class="btn btn-transparent">Cancel</button>
<button type="submit" class="btn btn-success animated wobble">&nbsp;Submit&nbsp;</button>
</div>
</div>
</form>

View File

@ -0,0 +1,4 @@
<!-- demo latetency <?php sleep(2) ?> -->
<p class="text-muted">Simulating latency with tiny php block on the server-side.</p>
<p>A timestamp this widget was created: Apr 24, 19:07:07</p>
<p>A timestamp this widget was updated: <?php echo date("M j, H:i:s") ?></p>

55
public/demo/grid/news.php Normal file
View File

@ -0,0 +1,55 @@
<!-- <?php sleep(2) //just some delay to simulate latency ?> -->
<ul class="news-list stretchable">
<li class="animated fadeInDown bg-widget-transparent">
<span class="icon bg-warning text-white">
<i class="fa fa-lock"></i>
</span>
<div class="news-item-info">
<h5 class="name no-margin mb-xs"><a href="#">Just now! Check update time</a></h5>
<p class="fs-mini">
Check this news item timestamp. There is a small server part that generates current timestamp so it
would be easier for you to see ajax widgets in action
</p>
<time class="help-block"><?php echo date("M j, H:i:s")?></time>
</div>
</li>
<li>
<span class="icon bg-danger text-white">
<i class="fa fa-star"></i>
</span>
<div class="news-item-info">
<h5 class="name no-margin mb-xs"><a href="#">First Human Colony on Mars</a></h5>
<p class="fs-mini">
First 700 people will take part in building first human settlement outside of Earth.
That's awesome, right?
</p>
<time class="help-block">Mar 20, 18:46</time>
</div>
</li>
<li>
<span class="icon bg-info text-white">
<i class="fa fa-microphone"></i>
</span>
<div class="news-item-info">
<h5 class="name no-margin mb-xs"><a href="#">Light Blue reached $300</a></h5>
<p class="fs-mini">
Light Blue Inc. shares just hit $300 price. "This was inevitable. It should
have happen sooner or later" - says NYSE expert.
</p>
<time class="help-block">Sep 25, 11:59</time>
</div>
</li>
<li>
<span class="icon bg-success text-white">
<i class="fa fa-eye"></i>
</span>
<div class="news-item-info">
<h5 class="name no-margin mb-xs"><a href="#">No more spying</a></h5>
<p class="fs-mini">
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor
incididunt ut labore et dolore magna aliqua.
</p>
<time class="help-block">Mar 20, 18:46</time>
</div>
</li>
</ul>

View File

@ -0,0 +1,53 @@
<?php sleep(2) ?>
<div class="list-group list-group-lg">
<a href="#" class="list-group-item animated fadeInDown bg-widget-transparent">
<span class="thumb-sm me-2">
<img class="rounded-circle" src="/images/people/a6.jpg" alt="...">
</span>
<div>
<h6 class="no-margin"><strong>Jenny Wilington</strong></h6>
<small>just now</small>
</div>
<i class="fa fa-circle ms-auto text-success mt-sm"></i>
</a>
<a href="#" class="list-group-item ">
<span class="thumb-sm me-2">
<img class="rounded-circle" src="/images/people/a1.jpg" alt="...">
</span>
<div>
<h6 class="m-0">Maikel Basso</h6>
<small class="text-muted">about 2 mins ago</small>
</div>
<i class="fa fa-circle ms-auto text-danger"></i>
</a>
<a href="#" class="list-group-item">
<span class="thumb-sm me-2">
<img class="rounded-circle" src="/images/people/a2.jpg" alt="...">
</span>
<div>
<h6 class="m-0">Ianus Arendse</h6>
<small class="text-muted">about 42 mins ago</small>
</div>
<i class="fa fa-circle ms-auto text-info"></i>
</a>
<a href="#" class="list-group-item">
<span class="thumb-sm me-2">
<img class="rounded-circle" src="/images/people/a3.jpg" alt="...">
</span>
<div>
<h6 class="m-0">Valdemar Landau</h6>
<small class="text-muted">one hour ago</small>
</div>
<i class="fa fa-circle ms-auto text-success"></i>
</a>
<a href="#" class="list-group-item mb-n-md">
<span class="thumb-sm me-2">
<img class="rounded-circle" src="/images/people/a4.jpg" alt="...">
</span>
<div>
<h6 class="m-0">Rick Teagan</h6>
<small class="text-muted">3 hours ago</small>
</div>
<i class="fa fa-circle ms-auto text-warning"></i>
</a>
</div>

BIN
public/favicon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

BIN
public/images/people/a1.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 75 KiB

BIN
public/images/people/a2.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 75 KiB

BIN
public/images/people/a3.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

BIN
public/images/people/a4.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

BIN
public/images/people/a5.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

BIN
public/images/people/a6.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

15
public/manifest.json Normal file
View File

@ -0,0 +1,15 @@
{
"short_name": "Light Blue 5.0.0 - Isomorphic React Dashboard",
"name": "Create React App Sample",
"icons": [
{
"src": "/favicon.png",
"sizes": "64x64 32x32 24x24 16x16",
"type": "image/x-icon"
}
],
"start_url": ".",
"display": "standalone",
"theme_color": "#000000",
"background_color": "#ffffff"
}

3
src/actions/README.md Normal file
View File

@ -0,0 +1,3 @@
# Action creators
Action Creators should go there

8
src/actions/alerts.js Normal file
View File

@ -0,0 +1,8 @@
export const DISMISS_ALERT = 'DISMISS_ALERT';
export function dismissAlert(id) {
return {
type: DISMISS_ALERT,
id,
};
}

44
src/actions/analytics.js Normal file
View File

@ -0,0 +1,44 @@
import axios from 'axios';
import mock from '../pages/analytics/mock';
import config from '../config';
export const RECEIVED_DATA_SUCCESS = 'RECEIVED_DATA_SUCCESS';
export const RECEIVING_DATA = 'RECEIVING_DATA';
export function receiveDataRequest() {
return (dispatch) => {
// We check if app runs with backend mode
if (!config.isBackend) {
dispatch(receivingData());
new Promise((resolve) => {
resolve(mock.backendData)
}).then(data => {
dispatch(receiveDataSuccess(mock.backendData));
})
}
else {
dispatch(receivingData());
axios.get('/analytics').then(res => {
dispatch(receiveDataSuccess(res.data));
})
}
};
}
export function receiveDataSuccess(payload) {
return {
type: RECEIVED_DATA_SUCCESS,
payload
}
}
export function receivingData() {
return {
type: RECEIVING_DATA
}
}

241
src/actions/auth.js Normal file
View File

@ -0,0 +1,241 @@
import axios from 'axios';
import { toast } from 'react-toastify';
import config from '../config';
import { push } from 'actions/navigation';
import Errors from '../components/FormItems/error/errors';
import { mockUser } from './mock';
import { decodeJwt } from '../core/jwt';
import {
fetchCurrentUser,
requestPasswordReset,
resetPasswordWithToken,
signInLocal,
signUp,
verifyEmailToken,
} from '../services/authService';
export const AUTH_FAILURE = 'AUTH_FAILURE';
export const LOGIN_REQUEST = 'LOGIN_REQUEST';
export const LOGIN_SUCCESS = 'LOGIN_SUCCESS';
export const LOGOUT_REQUEST = 'LOGOUT_REQUEST';
export const LOGOUT_SUCCESS = 'LOGOUT_SUCCESS';
export const RESET_REQUEST = 'RESET_REQUEST';
export const RESET_SUCCESS = 'RESET_SUCCESS';
export const PASSWORD_RESET_EMAIL_REQUEST = 'PASSWORD_RESET_EMAIL_REQUEST';
export const PASSWORD_RESET_EMAIL_SUCCESS = 'PASSWORD_RESET_EMAIL_SUCCESS';
export const AUTH_INIT_SUCCESS = 'AUTH_INIT_SUCCESS';
export const AUTH_INIT_ERROR = 'AUTH_INIT_ERROR';
export const REGISTER_REQUEST = 'REGISTER_REQUEST';
export const REGISTER_SUCCESS = 'REGISTER_SUCCESS';
function getAuthErrorMessage(error) {
return Errors.selectMessage(error);
}
export function authError(payload) {
return {
type: AUTH_FAILURE,
payload,
};
}
export function doInit() {
return async (dispatch) => {
if (!config.isBackend) {
dispatch({
type: AUTH_INIT_SUCCESS,
payload: {
currentUser: mockUser,
},
});
return;
}
try {
let currentUser = null;
const token = localStorage.getItem('token');
if (token) {
currentUser = await fetchCurrentUser();
}
dispatch({
type: AUTH_INIT_SUCCESS,
payload: {
currentUser,
},
});
} catch (error) {
Errors.handle(error);
dispatch({
type: AUTH_INIT_ERROR,
payload: error,
});
}
};
}
export function logoutUser() {
return (dispatch) => {
dispatch({
type: LOGOUT_REQUEST,
});
localStorage.removeItem('token');
localStorage.removeItem('user');
axios.defaults.headers.common.Authorization = '';
dispatch({
type: LOGOUT_SUCCESS,
});
dispatch(push('/login'));
};
}
export function receiveToken(token) {
return (dispatch) => {
const user = config.isBackend
? decodeJwt(token)
: {
email: config.auth.email,
user: {
id: 'default_no_connection_id_444',
},
};
localStorage.setItem('token', token);
localStorage.setItem('user', JSON.stringify(user));
axios.defaults.headers.common.Authorization = `Bearer ${token}`;
dispatch({
type: LOGIN_SUCCESS,
});
dispatch(push('/app'));
};
}
export function loginUser(creds) {
return async (dispatch) => {
if (!config.isBackend) {
dispatch(receiveToken('token'));
dispatch(doInit());
return;
}
dispatch({
type: LOGIN_REQUEST,
});
if (creds.social) {
window.location.href = `${config.baseURLApi}/auth/signin/${creds.social}?app=${config.redirectUrl}`;
return;
}
if (!creds.email || !creds.password) {
dispatch(authError('Something was wrong. Try again'));
return;
}
try {
const token = await signInLocal(creds);
dispatch(receiveToken(token));
dispatch(doInit());
} catch (error) {
dispatch(authError(getAuthErrorMessage(error)));
}
};
}
export function verifyEmail(token) {
return async (dispatch) => {
if (!config.isBackend) {
dispatch(push('/login'));
return;
}
try {
await verifyEmailToken(token);
toast.success('Your email was verified');
} catch (error) {
toast.error(getAuthErrorMessage(error));
} finally {
dispatch(push('/login'));
}
};
}
export function resetPassword(token, password) {
return async (dispatch) => {
if (!config.isBackend) {
dispatch(push('/login'));
return;
}
dispatch({
type: RESET_REQUEST,
});
try {
await resetPasswordWithToken(token, password);
dispatch({
type: RESET_SUCCESS,
});
toast.success('Password has been updated');
dispatch(push('/login'));
} catch (error) {
dispatch(authError(getAuthErrorMessage(error)));
}
};
}
export function sendPasswordResetEmail(email) {
return async (dispatch) => {
if (!config.isBackend) {
dispatch(push('/login'));
return;
}
dispatch({
type: PASSWORD_RESET_EMAIL_REQUEST,
});
try {
await requestPasswordReset(email);
dispatch({
type: PASSWORD_RESET_EMAIL_SUCCESS,
});
toast.success('Email with resetting instructions has been sent');
dispatch(push('/login'));
} catch (error) {
dispatch(authError(getAuthErrorMessage(error)));
}
};
}
export function registerUser(creds) {
return async (dispatch) => {
if (!config.isBackend) {
dispatch(push('/login'));
return;
}
dispatch({
type: REGISTER_REQUEST,
});
if (!creds.email || !creds.password) {
dispatch(authError('Something was wrong. Try again'));
return;
}
try {
await signUp(creds);
dispatch({
type: REGISTER_SUCCESS,
});
toast.success("You've been registered successfully. Please check your email for verification link");
dispatch(push('/login'));
} catch (error) {
dispatch(authError(getAuthErrorMessage(error)));
}
};
}

41
src/actions/layout.js Normal file
View File

@ -0,0 +1,41 @@
export const CHANGE_THEME = 'CHANGE_THEME';
export const CHANGE_SIDEBAR_COLOR = 'CHANGE_SIDEBAR_COLOR';
export const CHANGE_THEME_COLOR = 'CHANGE_THEME_COLOR';
export const NAVBAR_TYPE_TOGGLE = 'NAVBAR_TYPE_TOGGLE';
export const SIDEBAR_TYPE_TOGGLE = 'SIDEBAR_TYPE_TOGGLE';
export function changeTheme(payload) {
return {
type: CHANGE_THEME,
payload,
};
}
export function changeSidebarColor(payload) {
return {
type: CHANGE_SIDEBAR_COLOR,
payload,
};
}
export function changeThemeColor(payload) {
return {
type: CHANGE_THEME_COLOR,
payload,
};
}
export function navbarTypeToggle(value) {
return {
type: NAVBAR_TYPE_TOGGLE,
payload: value
}
}
export function sidebarTypeToggle(value) {
return {
type: SIDEBAR_TYPE_TOGGLE,
payload: value
}
}

24
src/actions/mock.js Normal file
View File

@ -0,0 +1,24 @@
export const mockUser = {
id: "98cea92c-84e5-4c0d-ac21-9998f4b23883",
firstName: "Admin",
authenticationUid: null,
avatar: null,
createdAt: "2020-05-12T11:04:00.864Z",
createdById: null,
deletedAt: null,
disabled: false,
email: "admin@flatlogic.com",
emailVerificationToken: null,
emailVerificationTokenExpiresAt: null,
emailVerified: true,
importHash: null,
lastName: null,
password: "$2b$12$EFuj2XoxivlGr.oiIvnvDulsE5iIBTngrLlrXMM/PkO//iInslWNW",
passwordResetToken: null,
passwordResetTokenExpiresAt: null,
phoneNumber: null,
provider: "local",
role: "admin",
updatedAt: "2020-05-12T11:04:00.864Z",
updatedById: null,
}

53
src/actions/navigation.js Normal file
View File

@ -0,0 +1,53 @@
export const OPEN_SIDEBAR = 'OPEN_SIDEBAR';
export const CLOSE_SIDEBAR = 'CLOSE_SIDEBAR';
export const CHANGE_ACTIVE_SIDEBAR_ITEM = 'CHANGE_ACTIVE_SIDEBAR_ITEM';
export const CHANGE_SIDEBAR_POSITION = 'CHANGE_SIDEBAR_POSITION';
export const CHANGE_SIDEBAR_VISIBILITY = 'CHANGE_SIDEBAR_VISIBILITY';
export function openSidebar() {
return {
type: OPEN_SIDEBAR,
};
}
export function changeSidebarPosition(nextPosition) {
return {
type: CHANGE_SIDEBAR_POSITION,
payload: nextPosition,
};
}
export function closeSidebar() {
return {
type: CLOSE_SIDEBAR,
};
}
export function changeActiveSidebarItem(activeItem) {
return {
type: CHANGE_ACTIVE_SIDEBAR_ITEM,
activeItem,
};
}
export function changeSidebarVisibility(nextVisibility) {
return {
type: CHANGE_SIDEBAR_VISIBILITY,
payload: nextVisibility,
};
}
export function push(path) {
return () => {
if (!path) {
return;
}
const normalizedPath = path.startsWith('/') ? path : `/${path}`;
if (window.location.pathname !== normalizedPath) {
window.history.pushState({}, '', normalizedPath);
window.dispatchEvent(new PopStateEvent('popstate'));
}
};
}

184
src/actions/products.js Normal file
View File

@ -0,0 +1,184 @@
import axios from 'axios';
import { toast } from 'react-toastify';
import mock from "../pages/products/backendMock";
import config from "../config";
export const RECEIVED_PRODUCTS = 'RECEIVED_PRODUCTS';
export const RECEIVING_PRODUCTS = 'RECEIVING_PRODUCTS';
export const RECEIVED_PRODUCT = 'RECEIVED_PRODUCT';
export const RECEIVING_PRODUCT = 'RECEIVING_PRODUCT';
export const UPDATED_PRODUCT = 'UPDATED_PRODUCT';
export const UPDATING_PRODUCT = 'UPDATING_PRODUCT';
export const DELETED_PRODUCT = 'DELETED_PRODUCT';
export const DELETING_PRODUCT = 'DELETING_PRODUCT';
export const RECEIVED_IMAGES = 'RECEIVED_IMAGES';
const toSerializable = (value) => {
if (value instanceof Date) {
return value.toISOString();
}
if (Array.isArray(value)) {
return value.map(toSerializable);
}
if (value && typeof value === 'object') {
return Object.entries(value).reduce((acc, [key, nestedValue]) => ({
...acc,
[key]: toSerializable(nestedValue),
}), {});
}
return value;
};
export function getProductsRequest() {
return (dispatch) => {
// We check if app runs with backend mode
if (!config.isBackend) {
dispatch(receiveProducts(mock));
}
else {
dispatch(receivingProducts());
axios.get('/products').then(res => {
dispatch(receiveProducts(res.data));
})
}
};
}
export function loadProductRequest(id) {
return (dispatch) => {
// We check if app runs with backend mode
if (!config.isBackend) {
dispatch(receiveProduct(mock.find(arr => arr.id === id)));
}
else {
dispatch(receivingProduct());
axios.get('/products/' + id).then(res => {
dispatch(receiveProduct(res.data));
})
}
};
}
export function updateProductRequest(product) {
return (dispatch) => {
// We check if app runs with backend mode
if (!config.isBackend) return;
dispatch(updatingProduct());
axios.put('/products/' + product.id, product).then(res => {
dispatch(updateProduct(res.data));
toast.success("Product has been Updated!");
})
};
}
export function createProductRequest(payload) {
return (dispatch) => {
// We check if app runs with backend mode
if (!config.isBackend) return;
dispatch(updatingProduct());
axios.post('/products', payload.product).then(res => {
dispatch(updateProduct(res.data));
payload.history.push('/app/ecommerce/management');
toast.success("Product has been Created!");
})
};
}
export function deleteProductRequest(payload) {
return (dispatch) => {
// We check if app runs with backend mode
if (!config.isBackend) return;
dispatch(deletingProduct(payload));
axios.delete('/products/' + payload.id).then(res => {
dispatch(deleteProduct({id: payload.id}));
if (payload.history.location.pathname !== '/app/ecommerce/management') {
payload.history.push('/app/ecommerce/management');
}
toast.success("Product has been Deleted!");
})
};
}
export function getProductsImagesRequest(payload) {
return (dispatch) => {
// We check if app runs with backend mode
if (!config.isBackend) return;
axios.get('/products/images-list').then(res => {
dispatch(receiveProductImages(res.data));
if (!payload.img && res.data.length) {
dispatch(updateProduct({id: payload.id, img: res.data[0]}));
}
})
};
}
export function receiveProductImages(payload) {
return {
type: RECEIVED_IMAGES,
payload
}
}
export function receiveProducts(payload) {
return {
type: RECEIVED_PRODUCTS,
payload: toSerializable(payload),
}
}
export function receivingProducts() {
return {
type: RECEIVING_PRODUCTS
}
}
export function receiveProduct(payload) {
return {
type: RECEIVED_PRODUCT,
payload: toSerializable(payload),
}
}
export function receivingProduct() {
return {
type: RECEIVING_PRODUCT
}
}
export function updateProduct(payload) {
return {
type: UPDATED_PRODUCT,
payload: toSerializable(payload),
}
}
export function updatingProduct() {
return {
type: UPDATING_PRODUCT
}
}
export function deleteProduct(payload) {
return {
type: DELETED_PRODUCT,
payload
}
}
export function deletingProduct(payload) {
return {
type: DELETING_PRODUCT,
payload
}
}

View File

@ -0,0 +1,134 @@
import Errors from 'components/FormItems/error/errors';
import { push } from 'actions/navigation';
import { doInit } from 'actions/auth';
import { toast } from 'react-toastify';
import config from '../config';
import { mockUser } from '../actions/mock';
import { updatePassword } from '../services/authService';
import { createUser, findUser, updateUser } from '../services/usersService';
const actions = {
doNew: () => {
return {
type: 'USERS_FORM_RESET',
};
},
doFind: (id) => async (dispatch) => {
if (!config.isBackend) {
dispatch({
type: 'USERS_FORM_FIND_SUCCESS',
payload: mockUser,
});
return;
}
try {
dispatch({
type: 'USERS_FORM_FIND_STARTED',
});
const record = await findUser(id);
dispatch({
type: 'USERS_FORM_FIND_SUCCESS',
payload: record,
});
} catch (error) {
Errors.handle(error);
dispatch({
type: 'USERS_FORM_FIND_ERROR',
});
dispatch(push('/admin/users'));
}
},
doCreate: (values) => async (dispatch) => {
try {
dispatch({
type: 'USERS_FORM_CREATE_STARTED',
});
if (config.isBackend) {
await createUser(values);
}
dispatch({
type: 'USERS_FORM_CREATE_SUCCESS',
});
toast.success('User created');
dispatch(push('/admin/users'));
} catch (error) {
Errors.handle(error);
dispatch({
type: 'USERS_FORM_CREATE_ERROR',
});
}
},
doUpdate: (id, values, isProfile) => async (dispatch) => {
try {
dispatch({
type: 'USERS_FORM_UPDATE_STARTED',
});
if (config.isBackend) {
await updateUser(id, values);
}
dispatch(doInit());
dispatch({
type: 'USERS_FORM_UPDATE_SUCCESS',
});
if (isProfile) {
toast.success('Profile updated');
} else {
toast.success('User updated');
dispatch(push('/admin/users'));
}
} catch (error) {
Errors.handle(error);
dispatch({
type: 'USERS_FORM_UPDATE_ERROR',
});
}
},
doChangePassword: ({newPassword, currentPassword}) => async (dispatch) => {
try {
dispatch({
type: 'USERS_FORM_UPDATE_STARTED',
});
if (config.isBackend) {
await updatePassword({newPassword, currentPassword});
}
dispatch({
type: 'USERS_PASSWORD_UPDATE_SUCCESS',
});
dispatch({
type: 'USERS_FORM_UPDATE_SUCCESS',
});
toast.success('Password has been updated');
dispatch(push('/app/main'));
} catch (error) {
Errors.handle(error);
dispatch({
type: 'USERS_FORM_UPDATE_ERROR',
});
}
},
};
export default actions;

View File

@ -0,0 +1,107 @@
import Errors from 'components/FormItems/error/errors';
import config from '../config';
import { mockUser } from '../actions/mock';
import { deleteUser, listUsers } from '../services/usersService';
function normalizeUsersPayload(response) {
if (Array.isArray(response)) {
return {
rows: response,
count: response.length,
};
}
const rows = Array.isArray(response && response.rows) ? response.rows : [];
const count = typeof (response && response.count) === 'number' ? response.count : rows.length;
return {
rows,
count,
};
}
const actions = {
doFetch: (filter, keepPagination = false) => async (dispatch) => {
if (!config.isBackend) {
dispatch({
type: 'USERS_LIST_FETCH_SUCCESS',
payload: {
rows: [mockUser],
count: 1,
},
});
} else {
try {
dispatch({
type: 'USERS_LIST_FETCH_STARTED',
payload: { filter, keepPagination },
});
const response = await listUsers();
const payload = normalizeUsersPayload(response);
dispatch({
type: 'USERS_LIST_FETCH_SUCCESS',
payload,
});
} catch (error) {
Errors.handle(error);
dispatch({
type: 'USERS_LIST_FETCH_ERROR',
});
}
}
},
doDelete: (id) => async (dispatch) => {
if (!config.isBackend) {
dispatch({
type: 'USERS_LIST_DELETE_ERROR',
});
} else {
try {
dispatch({
type: 'USERS_LIST_DELETE_STARTED',
});
await deleteUser(id);
dispatch({
type: 'USERS_LIST_DELETE_SUCCESS',
});
const response = await listUsers();
const payload = normalizeUsersPayload(response);
dispatch({
type: 'USERS_LIST_FETCH_SUCCESS',
payload,
});
} catch (error) {
Errors.handle(error);
dispatch({
type: 'USERS_LIST_DELETE_ERROR',
});
}
}
},
doOpenConfirm: (id) => async (dispatch) => {
dispatch({
type: 'USERS_LIST_OPEN_CONFIRM',
payload: {
id: id
},
});
},
doCloseConfirm: () => async (dispatch) => {
dispatch({
type: 'USERS_LIST_CLOSE_CONFIRM',
});
},
};
export default actions;

View File

@ -0,0 +1,81 @@
import React, { useEffect, useRef, useState } from 'react';
import PropTypes from 'prop-types';
function AnimatedNumber({
value,
initialValue,
duration,
stepPrecision,
formatValue,
}) {
const initial = Number.isFinite(initialValue) ? initialValue : Number(value) || 0;
const [displayValue, setDisplayValue] = useState(initial);
const previousValueRef = useRef(initial);
const frameRef = useRef(null);
useEffect(() => {
const to = Number(value);
const from = Number(previousValueRef.current) || 0;
if (!Number.isFinite(to)) {
setDisplayValue(value);
previousValueRef.current = value;
return undefined;
}
if (!duration || duration <= 0) {
setDisplayValue(to);
previousValueRef.current = to;
return undefined;
}
let startTime = null;
const tick = (timestamp) => {
if (!startTime) {
startTime = timestamp;
}
const progress = Math.min((timestamp - startTime) / duration, 1);
const next = from + (to - from) * progress;
const rounded = Number(next.toFixed(stepPrecision));
setDisplayValue(rounded);
if (progress < 1) {
frameRef.current = requestAnimationFrame(tick);
} else {
previousValueRef.current = to;
}
};
frameRef.current = requestAnimationFrame(tick);
return () => {
if (frameRef.current) {
cancelAnimationFrame(frameRef.current);
}
};
}, [duration, stepPrecision, value]);
if (typeof formatValue === 'function') {
return <>{formatValue(displayValue)}</>;
}
return <>{displayValue}</>;
}
AnimatedNumber.defaultProps = {
duration: 300,
formatValue: null,
initialValue: 0,
stepPrecision: 0,
};
AnimatedNumber.propTypes = {
duration: PropTypes.number,
formatValue: PropTypes.func,
initialValue: PropTypes.number,
stepPrecision: PropTypes.number,
value: PropTypes.oneOfType([PropTypes.number, PropTypes.string]).isRequired,
};
export default AnimatedNumber;

120
src/components/App.js Normal file
View File

@ -0,0 +1,120 @@
import React from 'react';
import { useDispatch, useSelector } from 'react-redux';
import {
BrowserRouter,
Navigate,
Route,
Routes,
} from 'react-router-dom';
import { ToastContainer } from 'react-toastify';
import { AdminRoute, UserRoute, AuthRoute } from './RouteComponents';
/* eslint-disable */
import ErrorPage from '../pages/error';
/* eslint-enable */
import '../styles/theme.scss';
import LayoutComponent from '../components/Layout';
import DocumentationLayoutComponent from '../documentation/DocumentationLayout';
import Login from '../pages/auth/login';
import Verify from '../pages/auth/verify';
import Register from '../pages/auth/register';
import Reset from '../pages/auth/reset';
import Forgot from '../pages/auth/forgot';
const CloseButton = ({ closeToast }) => (
<button
type="button"
onClick={closeToast}
className="Toastify__close-button notifications-close"
aria-label="Close notification"
>
<i className="la la-close" />
</button>
);
const App = () => {
const dispatch = useDispatch();
const currentUser = useSelector((store) => store.auth.currentUser);
return (
<div>
<ToastContainer
autoClose={5000}
hideProgressBar
closeButton={<CloseButton />}
/>
<BrowserRouter>
<Routes>
<Route path="/" element={<Navigate to="/app/main" replace />} />
<Route path="/app" element={<Navigate to="/app/main" replace />} />
<Route
path="/app/*"
element={(
<UserRoute dispatch={dispatch}>
<LayoutComponent />
</UserRoute>
)}
/>
<Route
path="/admin/*"
element={(
<AdminRoute currentUser={currentUser}>
<LayoutComponent />
</AdminRoute>
)}
/>
<Route
path="/documentation"
element={<Navigate to="/documentation/getting-started/overview" replace />}
/>
<Route path="/documentation/*" element={<DocumentationLayoutComponent />} />
<Route
path="/register"
element={(
<AuthRoute>
<Register />
</AuthRoute>
)}
/>
<Route
path="/login"
element={(
<AuthRoute>
<Login />
</AuthRoute>
)}
/>
<Route
path="/verify-email"
element={(
<AuthRoute>
<Verify />
</AuthRoute>
)}
/>
<Route
path="/password-reset"
element={(
<AuthRoute>
<Reset />
</AuthRoute>
)}
/>
<Route
path="/forgot"
element={(
<AuthRoute>
<Forgot />
</AuthRoute>
)}
/>
<Route path="/error" element={<ErrorPage />} />
<Route path="*" element={<Navigate to="/app/main/dashboard" replace />} />
</Routes>
</BrowserRouter>
</div>
);
};
export default App;

View File

@ -0,0 +1,48 @@
import React, { useLayoutEffect, useRef } from 'react';
function resizeTextarea(textarea, minRows) {
if (!textarea) {
return;
}
textarea.style.height = 'auto';
const lineHeight = parseInt(window.getComputedStyle(textarea).lineHeight, 10) || 20;
const minHeight = minRows * lineHeight;
const nextHeight = Math.max(textarea.scrollHeight, minHeight);
textarea.style.height = `${nextHeight}px`;
}
function AutoResizeTextarea({
rows = 2,
onChange,
style,
...rest
}) {
const textareaRef = useRef(null);
useLayoutEffect(() => {
resizeTextarea(textareaRef.current, rows);
}, [rows, rest.value]);
const handleChange = (event) => {
resizeTextarea(textareaRef.current, rows);
if (onChange) {
onChange(event);
}
};
return (
<textarea
{...rest}
ref={textareaRef}
rows={rows}
onChange={handleChange}
style={{
overflow: 'hidden',
...style,
}}
/>
);
}
export default AutoResizeTextarea;

View File

@ -0,0 +1,42 @@
import React from 'react';
import { Breadcrumb, BreadcrumbItem } from 'reactstrap';
import {
Link
} from 'react-router-dom';
const BreadcrumbHistory = ({ url }) => {
const renderBreadCrumbs = () => {
const route = url.split('/')
.slice(1)
.map((routeSegment) => routeSegment
.split('-')
.map((word) => word[0].toUpperCase() + word.slice(1))
.join(' '));
const length = route.length;
return route.map((item, index) => {
const middlewareUrl = `/${url.split('/').slice(1, index + 2).join('/')}`;
return (
<BreadcrumbItem key={middlewareUrl}>
{length === index + 1 ?
item :
<Link to={middlewareUrl}>
{item}
</Link>
}
</BreadcrumbItem>
);
});
};
return (
<div>
<Breadcrumb tag="nav" listTag="div">
<BreadcrumbItem>YOU ARE HERE</BreadcrumbItem>
{renderBreadCrumbs()}
</Breadcrumb>
</div>
);
};
export default BreadcrumbHistory;

View File

@ -0,0 +1,6 @@
{
"name": "BreadcrumbHistory",
"version": "0.0.0",
"private": true,
"main": "./BreadcrumbHistory.js"
}

View File

@ -0,0 +1,46 @@
import React from 'react';
import PropTypes from 'prop-types';
import s from './ColorPicker.module.scss';
const CustomColorPicker = ({ colors, activeColor, updateColor, customizationItem }) => {
if (customizationItem === 'navbar') {
return (
<div>
<ul className={s.colorsList}>
{Object.entries(colors).map((color) => (
<li
key={color[1]}
className={`${s.colorBox} ${(activeColor === color[1]) ? s.active : ''}`}
style={{ background: color[1] }}
onClick={() => updateColor(color[1])}
/>
))}
</ul>
</div>
);
}
return (
<div>
<ul className={s.colorsList}>
{Object.entries(colors).map((color) => (
<li
key={color[1]}
className={`${s.colorBox} ${(activeColor === color[0]) ? s.active : ''}`}
style={{ background: color[1] }}
onClick={() => updateColor(color[0])}
/>
))}
</ul>
</div>
);
};
CustomColorPicker.propTypes = {
colors: PropTypes.object,
activeColor: PropTypes.string,
updateColor: PropTypes.func,
customizationItem: PropTypes.string,
};
export default CustomColorPicker

View File

@ -0,0 +1,32 @@
@import "../../styles/app";
.colorsList {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
.colorBox {
min-width: 30px;
height: 30px;
border: 1px solid $border-color;
border-radius: 0;
cursor: pointer;
margin: 3px;
transition: $transition-base;
:global {
.rc-color-picker-trigger {
width: 100%;
height: 100%;
}
}
&:hover {
border-color: darken($border-color, 30%);
}
&.active {
border-color: darken($primary, 10%);
}
}
}

View File

@ -0,0 +1,6 @@
{
"name": "ColorPicker",
"version": "0.0.0",
"private": true,
"main": "./ColorPicker.js"
}

View File

@ -0,0 +1,75 @@
import { toast } from 'react-toastify';
/* global __APP_ENV__ */
const DEFAULT_ERROR_MESSAGE = 'Error';
const appEnv = typeof __APP_ENV__ !== 'undefined' ? __APP_ENV__ : {};
const runtimeNodeEnv =
appEnv.NODE_ENV || (typeof process !== 'undefined' && process.env ? process.env.NODE_ENV : undefined);
function selectErrorMessage(error) {
if (error && error.response && error.response.data) {
const data = error.response.data;
if (data.error && data.error.message) {
return data.error.message;
}
return String(data);
}
return error.message || DEFAULT_ERROR_MESSAGE;
}
function selectErrorCode(error) {
if (error && error.response && error.response.status) {
return error.response.status;
}
return 500;
}
function navigate(path) {
if (!path) {
return;
}
const normalizedPath = path.startsWith('/') ? path : `/${path}`;
if (window.location.pathname !== normalizedPath) {
window.history.pushState({}, '', normalizedPath);
window.dispatchEvent(new PopStateEvent('popstate'));
}
}
export default class Errors {
static handle(error) {
if (runtimeNodeEnv !== 'test') {
console.error(selectErrorMessage(error));
console.error(error);
}
if (selectErrorCode(error) === 403) {
navigate('/403');
return;
}
if (selectErrorCode(error) === 400) {
toast.error(selectErrorMessage(error));
return;
}
navigate('/500');
}
static errorCode(error) {
return selectErrorCode(error);
}
static selectMessage(error) {
return selectErrorMessage(error);
}
static showMessage(error) {
toast.error(selectErrorMessage(error));
}
}

View File

@ -0,0 +1,45 @@
export default class FormErrors {
static displayableError(
form,
fieldName,
externalErrorMessage = null,
) {
if (externalErrorMessage) {
return externalErrorMessage;
}
if (!form.touched[fieldName]) {
return null;
}
const errors = form.errors[fieldName];
if (!errors) {
return null;
}
if (Array.isArray(errors)) {
return errors[0];
}
return errors;
}
static validateStatus(
form,
fieldName,
externalErrorMessage,
) {
if (
this.displayableError(
form,
fieldName,
externalErrorMessage,
)
) {
return 'is-invalid';
}
return '';
}
}

View File

@ -0,0 +1,115 @@
import dayjs from 'core/date';
import * as yup from 'yup';
const formValidations = (fields, record={}) => {
const yupArray = {};
Object.keys(fields).forEach(field => {
const type = fields[field].type;
const label = fields[field].label;
const required = fields[field].required;
let yupConds = {};
switch(type) {
case 'boolean':
yupConds = yup
.bool()
.default(false)
break;
case 'date':
yupConds = yup
.mixed()
.nullable(true)
.test(
'is-date',
'',
(value) => {
if (!value) {
return true;
}
return dayjs(value, 'YYYY-MM-DD', true).isValid();
}
);
break;
case 'datetime':
yupConds = yup
.mixed()
.nullable(true)
break;
case 'decimal':
yupConds = yup
.number()
.nullable(true)
break;
case 'enum':
yupConds = yup
.string()
.nullable(true)
break;
case 'files':
yupConds = yup
.array()
.compact()
.ensure()
.nullable(true)
break;
case 'images':
yupConds = yup
.array()
.nullable(true)
break;
case 'int':
yupConds = yup
.number()
.integer()
.nullable(true)
break;
case 'user_many':
case 'relation_many':
yupConds = yup
.array()
.nullable(true)
break;
case 'user_one':
case 'relation_one':
yupConds = yup
.mixed()
.nullable(true)
break;
case 'stringArray':
yupConds = yup
.array()
.compact()
.ensure()
.of(yup.string().trim())
break;
case 'string':
yupConds = yup
.string()
.nullable(true)
.trim()
break;
default:
yupConds = yup
.string();
}
yupConds = yupConds.label(label);
if (required) {
yupConds = yupConds.required();
}
yupArray[field] = yupConds;
});
return yup.object().shape(yupArray);
}
export default formValidations;

View File

@ -0,0 +1,121 @@
import dayjs from 'core/date';
const isStringValue = (value) => typeof value === 'string' || value instanceof String;
const IniValues = (fields, record={}) => {
const iniArray = {};
Object.keys(fields).forEach(field => {
const type = fields[field].type;
const value = record[field];
let showValue = '';
switch(type) {
case 'boolean':
showValue = value;
break;
case 'date':
showValue = value
? dayjs(value, 'YYYY-MM-DD').toDate()
: null;
break;
case 'dateRange':
if (!value || !value.length) {
showValue = [];
}
else {
showValue = value.map((item) =>
item ? dayjs(item, 'YYYY-MM-DD').toDate() : null
);
}
break;
case 'datetime':
showValue = value ? dayjs(value).toDate() : null;
break;
case 'datetimeRange':
if (!value || !value.length) {
showValue = [];
}
else { showValue = value.map((item) =>
item ? dayjs(item).toDate() : null
);
}
break;
case 'decimal':
showValue = value;
break;
case 'decimalRange':
showValue = value || [];
break;
case 'enum':
if (!value || isStringValue(value)) {
showValue = value;
}
else {
showValue = value.id;
}
break;
case 'files':
showValue = value;
break;
case 'images':
showValue = value;
break;
case 'int':
showValue = value;
break;
case 'intRange':
showValue = value;
break;
case 'relation_many':
showValue = value;
break;
case 'relation_one':
showValue = value;
break;
case 'user_many':
showValue = value;
break;
case 'user_one':
showValue = value;
break;
case 'stringArray':
if (!value) {
showValue = [];
}
else if (Array.isArray(value)) {
showValue = value;
}
else {
showValue = [value];
}
break;
case 'string':
showValue = value;
break;
default:
showValue = value;
}
iniArray[field] = showValue;
});
return iniArray;
}
export default IniValues;

View File

@ -0,0 +1,95 @@
import React from 'react';
import PropTypes from 'prop-types';
import FormErrors from 'components/FormItems/formErrors';
import { FastField } from 'formik';
export const CheckboxFormItemNotFast = (props) => {
const {
name,
form,
hint,
size,
inputProps,
errorMessage,
required,
} = props;
const { label } = props.schema[name];
const sizeLabelClassName =
{
small: 'col-form-label-sm',
large: 'col-form-label-lg',
}[size] || '';
return (
<div className="form-group">
{!!label && (
<label
className={`col-form-label ${
required ? 'required' : null
} ${sizeLabelClassName}`}
htmlFor={name}
>
{label}
</label>
)}
<div>
<input
type="checkbox"
id={name}
name={name}
onChange={(event) => {
form.setFieldValue(
name,
!!event.target.checked,
);
form.setFieldTouched(name);
}}
checked={!!form.values[name]}
{...inputProps}
/>
</div>
<div className="invalid-feedback">
{FormErrors.displayableError(
form,
name,
errorMessage,
)}
</div>
{!!hint && (
<small className="form-text text-muted">
{hint}
</small>
)}
</div>
);
};
CheckboxFormItemNotFast.defaultProps = {};
CheckboxFormItemNotFast.propTypes = {
form: PropTypes.object.isRequired,
name: PropTypes.string.isRequired,
required: PropTypes.bool,
hint: PropTypes.string,
size: PropTypes.string,
errorMessage: PropTypes.string,
inputProps: PropTypes.object,
};
const CheckboxFormItem = (props) => (
<FastField name={props.name}>
{({ form }) => (
<CheckboxFormItemNotFast
{...props}
form={form}
/>
)}
</FastField>
);
export default CheckboxFormItem;

View File

@ -0,0 +1,86 @@
import PropTypes from 'prop-types';
import React from 'react';
import ImagesUploader from 'components/FormItems/uploaders/ImagesUploader';
import FormErrors from 'components/FormItems/formErrors';
import { FastField } from 'formik';
const ImagesFormItemNotFast = (props) => {
const {
name,
form,
hint,
path,
fileProps,
max,
inputProps,
required,
} = props;
const { label } = props.schema[name];
return (
<div className="form-group">
{!!label && (
<label
className={`col-form-label ${
required ? 'required' : null
}`}
htmlFor={name}
>
{label}
</label>
)}
<br />
<ImagesUploader
path={path}
schema={fileProps}
value={form.values[name]}
onChange={(value) => {
form.setFieldValue(name, value);
form.setFieldTouched(name);
}}
max={max}
{...inputProps}
/>
<div className="invalid-feedback">
{FormErrors.displayableError(form, name)}
</div>
{!!hint && (
<small className="form-text text-muted">
{hint}
</small>
)}
</div>
);
};
ImagesFormItemNotFast.defaultProps = {
max: undefined,
required: false,
};
ImagesFormItemNotFast.propTypes = {
path: PropTypes.string.isRequired,
required: PropTypes.bool,
form: PropTypes.object.isRequired,
name: PropTypes.string.isRequired,
hint: PropTypes.string,
formItemProps: PropTypes.object,
inputProps: PropTypes.object,
};
const ImagesFormItem = (props) => (
<FastField name={props.name}>
{({ form }) => (
<ImagesFormItemNotFast
{...props}
form={form}
/>
)}
</FastField>
);
export default ImagesFormItem;

View File

@ -0,0 +1,41 @@
import PropTypes from 'prop-types';
import React from 'react';
import ImagesUploader from 'components/FormItems/uploaders/ImagesUploader';
const ImagesViewItem = ({ label, value }) => {
const valueAsArray = () => {
if (!value) {
return [];
}
if (Array.isArray(value)) {
return value;
}
return [value];
};
if (!valueAsArray().length) {
return null;
}
return (
<div className="form-group">
<label className="col-form-label">
{label}
</label>
<br />
<ImagesUploader
readonly
value={valueAsArray()}
/>
</div>
);
};
ImagesViewItem.propTypes = {
label: PropTypes.string,
value: PropTypes.any,
};
export default ImagesViewItem;

View File

@ -0,0 +1,110 @@
import React from 'react';
import PropTypes from 'prop-types';
import FormErrors from '../formErrors';
import { FastField } from 'formik';
export const InputFormItemNotFast = (props) => {
const {
name,
form,
hint,
size,
password,
placeholder,
autoFocus,
autoComplete,
inputProps,
errorMessage,
required,
} = props;
const schemaField = props.schema ? props.schema[name] : undefined;
const label = schemaField ? schemaField.label : '';
const sizeLabelClassName =
{
small: 'col-form-label-sm',
large: 'col-form-label-lg',
}[size] || '';
const sizeInputClassName =
{
small: 'form-control-sm',
large: 'form-control-lg',
}[size] || '';
return (
<div className="form-group">
{!!label && (
<label
className={`col-form-label ${
required ? 'required' : null
} ${sizeLabelClassName}`}
htmlFor={name}
>
{label}
</label>
)}
<input
id={name}
type={password ? 'password' : 'text'}
onChange={(event) => {
form.setFieldValue(name, event.target.value);
form.setFieldTouched(name);
}}
value={(form.values && form.values[name]) || ''}
placeholder={placeholder || undefined}
autoFocus={autoFocus || undefined}
autoComplete={autoComplete || undefined}
className={`form-control ${sizeInputClassName} ${FormErrors.validateStatus(
form,
name,
errorMessage,
)}`}
{...inputProps}
/>
<div className="invalid-feedback">
{FormErrors.displayableError(
form,
name,
errorMessage,
)}
</div>
{!!hint && (
<small className="form-text text-muted">
{hint}
</small>
)}
</div>
);
};
InputFormItemNotFast.defaultProps = {
required: false,
};
InputFormItemNotFast.propTypes = {
form: PropTypes.object.isRequired,
name: PropTypes.string.isRequired,
required: PropTypes.bool,
type: PropTypes.string,
hint: PropTypes.string,
autoFocus: PropTypes.bool,
size: PropTypes.string,
prefix: PropTypes.string,
placeholder: PropTypes.string,
errorMessage: PropTypes.string,
inputProps: PropTypes.object,
};
const InputFormItem = (props) => (
<FastField name={props.name}>
{({ form }) => (
<InputFormItemNotFast
{...props}
form={form}
/>
)}
</FastField>
);
export default InputFormItem;

View File

@ -0,0 +1,103 @@
import React from 'react';
import PropTypes from 'prop-types';
import FormErrors from 'components/FormItems/formErrors';
import { FastField } from 'formik';
const RadioFormItemNotFast = (props) => {
const {
name,
form,
hint,
errorMessage,
required,
} = props;
const { label, options } = props.schema[name];
return (
<div className="form-group">
{!!label && (
<label
className={`col-form-label ${
required ? 'required' : null
}`}
>
{label}
</label>
)}
<br />
{options.map((option) => (
<div
key={option.value}
className="form-check form-check-inline"
>
<input
className={`form-check-input ${FormErrors.validateStatus(
form,
name,
errorMessage,
)}`}
type="radio"
id={`${name}-${option.value}`}
name={`${name}-${option.value}`}
value={option.value}
checked={option.value === form.values[name]}
onChange={(e) => {
form.setFieldValue(name, e.target.value);
form.setFieldTouched(name);
}}
/>
<label
htmlFor={`${name}-${option.value}`}
className="form-check-label"
>
{option.label}
</label>
</div>
))}
<div className="invalid-feedback">
{FormErrors.displayableError(
form,
name,
errorMessage,
)}
</div>
{!!hint && (
<small className="form-text text-muted">
{hint}
</small>
)}
</div>
);
};
RadioFormItemNotFast.defaultProps = {
required: false,
};
RadioFormItemNotFast.propTypes = {
form: PropTypes.object.isRequired,
name: PropTypes.string.isRequired,
schema: PropTypes.object.isRequired,
label: PropTypes.string,
hint: PropTypes.string,
required: PropTypes.bool,
errorMessage: PropTypes.string,
};
const RadioFormItem = (props) => (
<FastField name={props.name}>
{({ form }) => (
<RadioFormItemNotFast
{...props}
form={form}
/>
)}
</FastField>
);
export default RadioFormItem;

View File

@ -0,0 +1,101 @@
import React from 'react';
import PropTypes from 'prop-types';
import FormErrors from 'components/FormItems/formErrors';
import { FastField } from 'formik';
export const SwitchFormItemNotFast = (props) => {
const {
name,
form,
hint,
size,
inputProps,
errorMessage,
required,
} = props;
const { label } = props.schema[name];
const sizeLabelClassName =
{
small: 'col-form-label-sm',
large: 'col-form-label-lg',
}[size] || '';
return (
<div className="form-group d-flex align-items-baseline">
<div>
<input
type="checkbox"
id={name}
name={name}
onChange={(event) => {
form.setFieldValue(
name,
event.target.checked,
);
form.setFieldTouched(name);
}}
checked={!!form.values[name]}
{...inputProps}
/>
<label
htmlFor={name}
>
&#160;
</label>
</div>
{!!label && (
<label
className={`col-form-label ${
required ? 'required' : null
} ${sizeLabelClassName}`}
htmlFor={name}
>
{label}
</label>
)}
<div className="invalid-feedback">
{FormErrors.displayableError(
form,
name,
errorMessage,
)}
</div>
{!!hint && (
<small className="form-text text-muted">
{hint}
</small>
)}
</div>
);
};
SwitchFormItemNotFast.defaultProps = {};
SwitchFormItemNotFast.propTypes = {
form: PropTypes.object.isRequired,
name: PropTypes.string.isRequired,
required: PropTypes.bool,
hint: PropTypes.string,
size: PropTypes.string,
errorMessage: PropTypes.string,
inputProps: PropTypes.object,
};
const SwitchFormItem = (props) => (
<FastField name={props.name}>
{({ form }) => (
<SwitchFormItemNotFast
{...props}
form={form}
/>
)}
</FastField>
);
export default SwitchFormItem;

View File

@ -0,0 +1,111 @@
import React from 'react';
import PropTypes from 'prop-types';
import FormErrors from 'components/FormItems/formErrors';
import { FastField } from 'formik';
export const TextAreaFormItemNotFast = (props) => {
const {
label,
name,
form,
hint,
size,
type,
placeholder,
autoFocus,
autoComplete,
inputProps,
errorMessage,
required,
} = props;
const sizeLabelClassName =
{
small: 'col-form-label-sm',
large: 'col-form-label-lg',
}[size] || '';
const sizeInputClassName =
{
small: 'form-control-sm',
large: 'form-control-lg',
}[size] || '';
return (
<div className="form-group">
{!!label && (
<label
className={`col-form-label ${
required ? 'required' : null
} ${sizeLabelClassName}`}
htmlFor={name}
>
{label}
</label>
)}
<textarea
id={name}
type={type}
onChange={(event) => {
form.setFieldValue(name, event.target.value);
form.setFieldTouched(name);
}}
value={form.values[name] || ''}
placeholder={placeholder || undefined}
autoFocus={autoFocus || undefined}
autoComplete={autoComplete || undefined}
className={`form-control ${sizeInputClassName} ${FormErrors.validateStatus(
form,
name,
errorMessage,
)}`}
{...inputProps}
/>
<div className="invalid-feedback">
{FormErrors.displayableError(
form,
name,
errorMessage,
)}
</div>
{!!hint && (
<small className="form-text text-muted">
{hint}
</small>
)}
</div>
);
};
TextAreaFormItemNotFast.defaultProps = {
type: 'text',
required: false,
};
TextAreaFormItemNotFast.propTypes = {
form: PropTypes.object.isRequired,
name: PropTypes.string.isRequired,
required: PropTypes.bool,
type: PropTypes.string,
label: PropTypes.string,
hint: PropTypes.string,
autoFocus: PropTypes.bool,
size: PropTypes.string,
prefix: PropTypes.string,
placeholder: PropTypes.string,
errorMessage: PropTypes.string,
inputProps: PropTypes.object,
};
const TextAreaFormItem = (props) => (
<FastField name={props.name}>
{({ form }) => (
<TextAreaFormItemNotFast
{...props}
form={form}
/>
)}
</FastField>
);
export default TextAreaFormItem;

View File

@ -0,0 +1,39 @@
import PropTypes from 'prop-types';
import React from 'react';
const TextViewItem = ({ label, value, prefix }) => {
if (
!value &&
value !== 0 &&
value !== false
) {
return null;
}
const displayValue = `${
prefix ? `${prefix} ` : ''
}${value}`;
return (
<div className="form-group">
<label className="col-form-label">
{label}
</label>
<input
type="text"
readOnly
className="form-control-plaintext"
value={displayValue}
/>
</div>
);
};
TextViewItem.propTypes = {
label: PropTypes.string,
value: PropTypes.any,
prefix: PropTypes.string,
};
export default TextViewItem;

View File

@ -0,0 +1,39 @@
import React from 'react';
import PropTypes from 'prop-types';
import { FastField } from 'formik';
const ViewFormItemNotFast = ({ label, name, form }) => (
<div className="form-group">
<label className="col-form-label" htmlFor={name}>
{label}
</label>
<input
type="text"
readOnly
className="form-control-plaintext"
id={name}
value={form.values[name]}
/>
</div>
);
ViewFormItemNotFast.defaultProps = {};
ViewFormItemNotFast.propTypes = {
form: PropTypes.object.isRequired,
name: PropTypes.string.isRequired,
label: PropTypes.string,
};
const ViewFormItem = (props) => (
<FastField name={props.name}>
{({ form }) => (
<ViewFormItemNotFast
{...props}
form={form}
/>
)}
</FastField>
);
export default ViewFormItem;

View File

@ -0,0 +1,39 @@
import dayjs from 'core/date';
const PreparedValues = (fields, record={}) => {
const preparedArray = {};
Object.keys(fields).forEach(field => {
const type = fields[field].type;
const value = record[field];
let preparedValue = '';
switch(type) {
case 'date':
preparedValue = value
? dayjs(value, 'YYYY-MM-DD').toDate()
: null;
break;
case 'user_many':
case 'relation_many':
if (!value || !value.length) {
preparedValue = [];
}
else {
preparedValue = value.map((item) => item.id);
}
break;
case 'user_one':
case 'relation_one':
preparedValue = value ? value.id : null;
break;
default:
preparedValue = value;
}
preparedArray[field] = preparedValue;
});
return preparedArray;
}
export default PreparedValues;

View File

@ -0,0 +1,21 @@
import styled from 'styled-components';
const ButtonLink = styled.button`
background-color: transparent;
border: none;
cursor: pointer;
color: var(--link-color);
text-decoration: none;
display: inline;
margin: 0;
padding: 0;
&:hover {
text-decoration: none;
}
&:focus {
text-decoration: none;
}
`;
export default ButtonLink;

View File

@ -0,0 +1,22 @@
import styled from 'styled-components';
const ImagesUploaderWrapper = styled.div`
.img-card:hover .img-buttons {
display: block;
}
.img-buttons {
display: none;
position: relative;
bottom: 2.4rem;
width: calc(100px);
text-align: center;
background-color: rgba(0, 0, 0, 0.5);
}
.img-buttons * {
color: white;
}
`;
export default ImagesUploaderWrapper;

View File

@ -0,0 +1,153 @@
import React, { useRef, useState } from 'react';
import PropTypes from 'prop-types';
import FileUploader from 'components/FormItems/uploaders/UploadService';
import Errors from 'components/FormItems/error/errors';
const FilesUploader = (props) => {
const [loading, setLoading] = useState(false);
const input = useRef(null);
const value = () => {
const { value } = props;
if (!value) {
return [];
}
return Array.isArray(value) ? value : [value];
};
const fileList = () => {
return value().map((item) => ({
uid: item.id || undefined,
name: item.name,
status: 'done',
url: item.publicUrl,
}));
};
const handleRemove = (id) => {
props.onChange(
value().filter((item) => item.id !== id),
);
};
const handleChange = async (event) => {
try {
const files = event.target.files;
if (!files || !files.length) {
return;
}
let file = files[0];
FileUploader.validate(file, props.schema);
setLoading(true);
file = await FileUploader.upload(
props.path,
file,
props.schema,
);
input.current.value = '';
setLoading(false);
props.onChange([...value(), file]);
} catch (error) {
input.current.value = '';
console.log('error', error);
setLoading(false);
Errors.showMessage(error);
}
};
const formats = () => {
const { schema } = props;
if (schema && schema.formats) {
return schema.formats
.map((format) => `.${format}`)
.join(',');
}
return undefined;
};
const { max, readonly } = props;
const uploadButton = (
<label
className="btn btn-outline-secondary px-4 mb-2"
style={{ cursor: 'pointer' }}
>
{'Upload a file'}
<input
style={{ display: 'none' }}
disabled={loading || readonly}
accept={formats()}
type="file"
onChange={handleChange}
ref={input}
/>
</label>
);
return (
<div>
{readonly || (max && fileList().length >= max)
? null
: uploadButton}
{value() && value().length ? (
<div>
{value().map((item) => {
return (
<div key={item.id}>
<i className="la la-link text-muted me-2"></i>
<a
href={item.publicUrl}
target="_blank"
rel="noopener noreferrer"
download
>
{item.name}
</a>
{!readonly && (
<button
className="btn btn-link"
type="button"
onClick={() =>
handleRemove(item.id)
}
>
<i className="la la-times"></i>
</button>
)}
</div>
);
})}
</div>
) : null}
</div>
);
};
FilesUploader.propTypes = {
readonly: PropTypes.bool,
path: PropTypes.string,
max: PropTypes.number,
schema: PropTypes.shape({
image: PropTypes.bool,
size: PropTypes.number,
formats: PropTypes.arrayOf(PropTypes.string),
}),
value: PropTypes.any,
onChange: PropTypes.func,
};
export default FilesUploader;

View File

@ -0,0 +1,169 @@
import React, { useRef, useState } from 'react';
import PropTypes from 'prop-types';
import FileUploader from 'components/FormItems/uploaders/UploadService';
import Errors from 'components/FormItems/error/errors';
import ImagesUploaderWrapper from 'components/FormItems/style/ImagesUploaderWrapper';
const ImagesUploader = (props) => {
const [loading, setLoading] = useState(false);
const [, setPreviewImage] = useState({
imageSrc: null,
imageAlt: null,
});
const input = useRef(null);
const value = () => {
const { value } = props;
if (!value) {
return [];
}
return Array.isArray(value) ? value : [value];
};
const fileList = () => {
return value().map((item) => ({
uid: item.id || undefined,
name: item.name,
status: 'done',
url: item.publicUrl,
}));
};
const handleRemove = (id) => {
props.onChange(
value().filter((item) => item.id !== id),
);
};
const handleChange = async (event) => {
try {
const files = event.target.files;
if (!files || !files.length) {
return;
}
let file = files[0];
FileUploader.validate(file, props.schema);
setLoading(true);
file = await FileUploader.upload(
props.path,
file,
props.schema,
);
input.current.value = '';
setLoading(false);
props.onChange([...value(), file]);
} catch (error) {
input.current.value = '';
console.log('error', error);
setLoading(false);
Errors.showMessage(error);
}
};
const doPreviewImage = (image) => {
setPreviewImage({
imageSrc: image.publicUrl,
imageAlt: image.name,
});
};
const { max, readonly } = props;
const uploadButton = (
<label
className="btn btn-outline-secondary px-4 mb-2"
style={{ cursor: 'pointer' }}
>
{'Upload an image'}
<input
style={{ display: 'none' }}
disabled={loading || readonly}
accept="image/*"
type="file"
onChange={handleChange}
ref={input}
/>
</label>
);
return (
<ImagesUploaderWrapper>
{readonly || (max && fileList().length >= max)
? null
: uploadButton}
{value() && value().length ? (
<div className="d-flex flex-row flex-wrap">
{value().map((item) => {
return (
<div
className="me-2 mb-2 img-card"
style={{ height: '100px' }}
key={item.id}
>
<img
alt={item.name}
src={item.publicUrl}
className="img-thumbnail"
style={{
width: '100px',
height: '100px',
objectFit: 'cover',
}}
/>
<div className="img-buttons rounded-bottom">
<button
type="button"
className="btn btn-link"
onClick={() =>
doPreviewImage(item)
}
>
<i className="la la-search"></i>
</button>
{!readonly && (
<button
type="button"
className="btn btn-link ms-2"
onClick={() =>
handleRemove(item.id)
}
>
<i className="la la-times"></i>
</button>
)}
</div>
</div>
);
})}
</div>
) : null}
</ImagesUploaderWrapper>
);
};
ImagesUploader.propTypes = {
readonly: PropTypes.bool,
path: PropTypes.string,
max: PropTypes.number,
schema: PropTypes.shape({
image: PropTypes.bool,
size: PropTypes.number,
formats: PropTypes.arrayOf(PropTypes.string),
}),
value: PropTypes.any,
onChange: PropTypes.func,
};
export default ImagesUploader;

View File

@ -0,0 +1,87 @@
import { v4 as uuid } from 'uuid';
import Axios from 'axios';
import config from 'config';
function extractExtensionFrom(filename) {
if (!filename) {
return null;
}
const regex = /(?:\.([^.]+))?$/;
return regex.exec(filename)[1];
}
export default class FileUploader {
static validate(file, schema) {
if (!schema) {
return;
}
if (schema.image) {
if (!file.type.startsWith('image')) {
throw new Error('You must upload an image');
}
}
if (schema.size && file.size > schema.size) {
throw new Error(
'File is too big.'
);
}
const extension = extractExtensionFrom(file.name);
if (
schema.formats &&
!schema.formats.includes(extension)
) {
throw new Error('Invalid format');
}
}
static async upload(path, file, schema) {
try {
this.validate(file, schema);
} catch (error) {
return Promise.reject(error);
}
const extension = extractExtensionFrom(file.name);
const id = uuid();
const filename = `${id}.${extension}`;
const privateUrl = `${path}/${filename}`;
const publicUrl = await this.uploadToServer(
file,
path,
filename,
);
return {
id: id,
name: file.name,
sizeInBytes: file.size,
privateUrl,
publicUrl,
new: true,
};
}
static async uploadToServer(file, path, filename) {
const formData = new FormData();
formData.append('file', file);
formData.append('filename', filename);
const uri = `${config.baseURLApi}/file/upload/${path}`;
await Axios.post(uri, formData,
{
headers: {
'Content-Type': 'multipart/form-data',
},
},
);
const privateUrl = `${path}/${filename}`;
return `${config.baseURLApi}/file/download?privateUrl=${privateUrl}`;
}
}

View File

@ -0,0 +1,20 @@
import React from 'react';
function GoogleMapFrame({ center, zoom = 12, title = 'Google map' }) {
const src = `https://maps.google.com/maps?q=${center.lat},${center.lng}&z=${zoom}&output=embed`;
return (
<iframe
title={title}
src={src}
width="100%"
height="100%"
style={{ border: 0 }}
loading="lazy"
referrerPolicy="no-referrer-when-downgrade"
allowFullScreen
/>
);
}
export default GoogleMapFrame;

View File

@ -0,0 +1,256 @@
import React, { useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import {
Navbar,
Nav,
NavItem,
NavLink,
InputGroupText,
InputGroup,
Input,
UncontrolledAlert,
Dropdown,
Collapse,
DropdownToggle,
DropdownMenu,
DropdownItem,
Badge,
ButtonGroup,
Button,
Form,
} from 'reactstrap';
import Notifications from '../Notifications';
import PowerIcon from '../Icons/HeaderIcons/PowerIcon';
import BellIcon from '../Icons/HeaderIcons/BellIcon';
import SettingsIcon from '../Icons/HeaderIcons/SettingsIcon';
import MessageIcon from '../Icons/HeaderIcons/MessageIcon';
import BurgerIcon from '../Icons/HeaderIcons/BurgerIcon';
import SearchIcon from '../Icons/HeaderIcons/SearchIcon';
import ArrowIcon from '../Icons/HeaderIcons/ArrowIcon';
import { logoutUser } from '../../actions/auth';
import { openSidebar, closeSidebar, changeSidebarPosition, changeSidebarVisibility } from '../../actions/navigation';
import sender1 from '../../images/people/a1.jpg';
import sender2 from '../../images/people/a5.jpg';
import sender3 from '../../images/people/a4.jpg';
import adminDefault from '../../images/chat/chat2.png';
import s from './Header.module.scss';
function Header() {
const dispatch = useDispatch();
const isSidebarOpened = useSelector((store) => store.navigation.sidebarOpened);
const sidebarVisibility = useSelector((store) => store.navigation.sidebarVisibility);
const sidebarPosition = useSelector((store) => store.navigation.sidebarPosition);
const user = useSelector((store) => store.auth.currentUser);
const [messagesOpen, setMessagesOpen] = useState(false);
const [supportOpen, setSupportOpen] = useState(false);
const [settingsOpen, setSettingsOpen] = useState(false);
const [searchFocused, setSearchFocused] = useState(false);
const [searchOpen, setSearchOpen] = useState(false);
const [notificationsOpen, setNotificationsOpen] = useState(false);
const avatar = user && user.avatar && user.avatar.length && user.avatar[0].publicUrl;
const firstUserLetter = user && (user.firstName || user.email)[0].toUpperCase();
const doLogout = () => {
dispatch(logoutUser());
};
const toggleSidebar = () => {
if (isSidebarOpened) {
dispatch(closeSidebar());
} else {
dispatch(openSidebar());
}
};
const moveSidebar = (position) => {
dispatch(changeSidebarPosition(position));
};
const toggleVisibilitySidebar = (visibility) => {
dispatch(changeSidebarVisibility(visibility));
};
return (
<Navbar className="d-print-none">
<div className={s.burger}>
<NavLink onClick={toggleSidebar} className={`d-md-none ${s.navItem} text-white`} href="#">
<BurgerIcon className={s.headerIcon} />
</NavLink>
</div>
<div className={`d-print-none ${s.root}`}>
<UncontrolledAlert className="me-3 d-lg-down-none animate__animated animate__bounceIn animate__delay-1s">
Check out Light Blue
<button
className="btn-link"
onClick={() => setSettingsOpen(true)}
>
<SettingsIcon className={`${s.settingsIcon} btn-link`} />
</button> on the right!
</UncontrolledAlert>
<Collapse className={`${s.searchCollapse} ms-lg-0 me-md-3`} isOpen={searchOpen}>
<InputGroup className={`${s.navbarForm} ${searchFocused ? s.navbarFormFocused : ''}`}>
<InputGroupText className={s.inputAddon}>
<i className="fa fa-search" />
</InputGroupText>
<Input
id="search-input-2" placeholder="Search..." className="input-transparent"
onFocus={() => setSearchFocused(true)}
onBlur={() => setSearchFocused(false)}
/>
</InputGroup>
</Collapse>
<Form className="d-md-down-none mx-3 my-auto">
<InputGroup className={`input-group-no-border ${s.searchForm}`} >
<InputGroupText className={s.inputGroupText}>
<SearchIcon className={s.headerIcon} />
</InputGroupText>
<Input id="search-input" className="input-transparent" placeholder="Search Dashboard" />
</InputGroup>
</Form>
<Nav className="ms-md-0">
<Dropdown nav isOpen={notificationsOpen} toggle={() => setNotificationsOpen((prev) => !prev)} id="basic-nav-dropdown" className={`${s.notificationsMenu}`} >
<DropdownToggle nav caret style={{ color: '#C1C3CF', padding: 0 }}>
<span className={`${s.avatar} rounded-circle float-start`}>
{avatar ? (
<img src={avatar} onError={e => e.target.src = adminDefault} alt="..." title={user && (user.firstName || user.email)} />
) : user && user.role === 'admin' ? (
<img src={adminDefault} onError={e => e.target.src = adminDefault} alt="..." title={user && (user.firstName || user.email)} />
) : <span title={user && (user.firstName || user.email)}>{firstUserLetter}</span>
}
</span>
<span className={`small d-sm-down-none ${s.adminEmail}`}>{user ? (user.firstName || user.email) : 'Philip Smith'}</span>
<Badge className={`d-sm-down-none ${s.badge}`} color="danger">9</Badge>
</DropdownToggle>
<DropdownMenu className={`${s.notificationsWrapper} py-0 animate__animated animate__faster animate__fadeInUp`}>
<Notifications />
</DropdownMenu>
</Dropdown>
<NavItem className="d-lg-none">
<NavLink onClick={() => setSearchOpen((prev) => !prev)} className={s.navItem} href="#">
<SearchIcon addId="header-search" className={s.headerIcon} />
</NavLink>
</NavItem>
<Dropdown nav isOpen={messagesOpen} toggle={() => setMessagesOpen((prev) => !prev)}>
<DropdownToggle nav className={`d-sm-down-none ${s.navItem} text-white`}>
<MessageIcon className={s.headerIcon} />
</DropdownToggle>
<DropdownMenu className={`${s.dropdownMenu} ${s.messages}`}>
<DropdownItem>
<img className={s.image} src={sender1} alt="" />
<div className={s.details}>
<div>Jane Hew</div>
<div className={s.text}>
Hey, John! How is it going? ...
</div>
</div>
</DropdownItem>
<DropdownItem>
<img className={s.image} src={sender2} alt="" />
<div className={s.details}>
<div>Alies Rumiancaŭ</div>
<div className={s.text}>
I will definitely buy this template
</div>
</div>
</DropdownItem>
<DropdownItem>
<img className={s.image} src={sender3} alt="" />
<div className={s.details}>
<div>Michał Rumiancaŭ</div>
<div className={s.text}>
Is it really Lore ipsum? Lore ...
</div>
</div>
</DropdownItem>
<DropdownItem>
{/* eslint-disable-next-line */}
<a href="#" className="text-white">
See all messages <ArrowIcon className={s.headerIcon} maskName="messagesArrow" />
</a>
</DropdownItem>
</DropdownMenu>
</Dropdown>
<NavItem className={`${s.divider} d-none d-sm-block`} />
<Dropdown className="d-none d-sm-block" nav isOpen={settingsOpen} toggle={() => setSettingsOpen((prev) => !prev)}>
<DropdownToggle nav className={`${s.navItem} text-white`}>
<SettingsIcon addId="header-settings" className={s.headerIcon} />
</DropdownToggle>
<DropdownMenu className={`${s.dropdownMenu} ${s.settings}`}>
<h6>Sidebar on the</h6>
<ButtonGroup size="sm">
<Button color="primary" onClick={() => moveSidebar('left')} className={sidebarPosition === 'left' ? 'active' : ''}>Left</Button>
<Button color="primary" onClick={() => moveSidebar('right')} className={sidebarPosition === 'right' ? 'active' : ''}>Right</Button>
</ButtonGroup>
<h6 className="mt-2">Sidebar</h6>
<ButtonGroup size="sm">
<Button color="primary" onClick={() => toggleVisibilitySidebar('show')} className={sidebarVisibility === 'show' ? 'active' : ''}>Show</Button>
<Button color="primary" onClick={() => toggleVisibilitySidebar('hide')} className={sidebarVisibility === 'hide' ? 'active' : ''}>Hide</Button>
</ButtonGroup>
</DropdownMenu>
</Dropdown>
<Dropdown className="d-none d-sm-block" nav isOpen={supportOpen} toggle={() => setSupportOpen((prev) => !prev)}>
<DropdownToggle nav className={`${s.navItem} text-white`}>
<BellIcon className={s.headerIcon} />
<span className={s.count}></span>
</DropdownToggle>
<DropdownMenu className={`${s.dropdownMenu} ${s.support}`}>
<DropdownItem>
<Badge color="danger"><i className="fa fa-bell-o" /></Badge>
<div className={s.details}>
Check out this awesome ticket
</div>
</DropdownItem>
<DropdownItem>
<Badge color="warning"><i className="fa fa-question-circle" /></Badge>
<div className={s.details}>
What is the best way to get ...
</div>
</DropdownItem>
<DropdownItem>
<Badge color="success"><i className="fa fa-info-circle" /></Badge>
<div className={s.details}>
This is just a simple notification
</div>
</DropdownItem>
<DropdownItem>
<Badge color="info"><i className="fa fa-plus" /></Badge>
<div className={s.details}>
12 new orders has arrived today
</div>
</DropdownItem>
<DropdownItem>
<Badge color="danger"><i className="fa fa-tag" /></Badge>
<div className={s.details}>
One more thing that just happened
</div>
</DropdownItem>
<DropdownItem>
{/* eslint-disable-next-line */}
<a href="#" className="text-white">
See all tickets <ArrowIcon className={s.headerIcon} maskName="bellArrow" />
</a>
</DropdownItem>
</DropdownMenu>
</Dropdown>
<NavItem>
<NavLink onClick={doLogout} className={`${s.navItem} text-white`} href="#">
<PowerIcon className={s.headerIcon} />
</NavLink>
</NavItem>
</Nav>
</div>
</Navbar>
);
}
export default Header;

View File

@ -0,0 +1,410 @@
@import '../../styles/app';
.root {
display: flex;
justify-content: flex-end !important;
@media (max-width: breakpoint-max(sm)) {
margin-bottom: 50px;
}
ul > li > a {
padding: 0.5rem 12px;
@media(max-width: 580px) {
padding: 0.5rem 6px;
}
}
:global {
.alert {
height: 30px;
display: flex;
align-items: center;
margin: auto;
transition: margin-top 0.2s ease;
background: #12142B80;
border: none;
font-size: 1rem;
line-height: 20px;
padding: 5px 8px;
color: rgba(255, 255, 255, 0.6);
border-radius: 10px;
padding-right: 30px;
@media (max-width: 1255px) {
display: none !important;
}
button.btn-close {
color: $icon-blue;
font-weight: normal;
font-size: 18px !important;
margin-top: 1px !important;
}
.btn-link > svg {
vertical-align: bottom;
margin-left: 3px;
}
}
.input-transparent.form-control {
padding-left: $input-btn-padding-x !important;
}
}
}
.logo {
position: absolute;
@media (min-height: 940px) {
position: fixed;
}
left: 56px;
top: 18px;
z-index: 1;
font-size: 16px;
font-weight: normal;
color: $white;
&:hover,
&:focus {
color: $white;
}
@media (max-width: breakpoint-max(sm)) {
top: 10px;
left: 15px;
strong {
display: block;
}
}
&.logoHidden {
display: none;
}
}
.searchCollapse {
display: block;
@media (max-width: breakpoint-max(sm)) {
display: none;
position: absolute !important;
top: 60px;
left: 0;
right: 0;
&:global(.collapsing) {
display: block;
}
.navbarForm {
width: auto;
margin: 0 2.5641%;
}
}
&:global(.collapse) {
display: none;
}
}
.navbarForm {
padding: 6px 0;
margin-left: 10px;
width: 200px;
transition: width 0.2s ease-in-out;
.inputAddon {
border: none;
background-color: transparentize($text-transparent, 0.1);
transition: background-color ease-in-out 0.15s;
}
input {
font-size: 13px;
color: $white;
background-color: transparentize($text-transparent, 0.1);
border: none;
padding: 0.6rem 0.85rem 0.6rem 0;
min-height: 30px !important;
&:focus {
box-shadow: $input-box-shadow !important;
}
}
}
.navbarFormFocused {
width: 240px;
}
.divider {
display: block;
width: 1px;
margin: 10px 4px;
background: $icon-color;
}
.navItem {
font-size: 1.5rem;
outline: 0;
text-align: center;
&:hover,
&:focus {
color: $white !important;
}
:global(.glyphicon),
:global(.fa) {
vertical-align: baseline;
}
}
.glyphicon {
color: #3979F6;
}
.image {
float: left;
width: 40px;
margin-top: 7px;
border-radius: 50%;
}
.imageAccount {
width: 50px;
margin-right: 5px;
}
.dropdownMenu {
background: $main-background !important;
box-shadow: 0 0 40px 2px rgba(#020202,.5);
border: none;
color: $white;
@media (max-width: breakpoint-max(xs)) {
right: auto;
left: -100px;
}
&::after {
left: auto !important;
right: 15px;
@media (max-width: breakpoint-max(xs)) {
right: 112px;
}
}
:global(.show) > & {
display: block;
}
button:hover {
background-color: $widget-bg;
}
}
.messages {
button {
display: flex;
height: 60px;
font-weight: $font-weight-base;
padding-left: $spacer;
padding-right: $spacer;
&:last-child {
height: 30px;
justify-content: center;
}
}
.details {
margin-left: 10px;
margin-top: 7px;
.text {
font-size: $font-size-sm;
color: #ddd;
}
}
}
.support {
&::after {
@media (max-width: breakpoint-max(xs)) {
right: 102px;
}
}
:global(.badge) {
padding-left: 5px;
padding-right: 5px;
}
button {
display: flex;
padding: 5px 10px;
font-weight: $font-weight-base;
&:last-child {
height: 30px;
justify-content: center;
}
.details {
margin-left: 7px;
font-size: $font-size-sm;
}
}
}
.account {
width: 180px !important;
section {
padding: 5px 10px;
font-weight: normal;
}
button {
padding: 7px 10px;
font-weight: $font-weight-thin;
a {
color: $white;
padding: 0;
}
i {
margin-right: 3px;
}
}
}
.settings {
border-radius: 3px !important;
width: 122px !important;
text-align: center !important;
min-width: auto;
left: -40px !important;
h6 {
color: #fff;
}
&::after {
right: 53px !important;
left: auto;
}
}
.count {
position: absolute;
width: 6px;
height: 6px;
bottom: 8px;
right: 11px;
background: $green;
border-radius: 50%;
}
.notificationsMenu {
padding: 0 12px;
> a {
background-color: transparent!important;
}
@media(max-width: 580px) {
padding: 0;
}
:global .dropdown-menu {
left: auto !important;
right: 0 !important;
top: $navbar-height !important;
}
::after {
padding: 0;
margin: 0;
}
@media(max-width: 580px) {
:global .dropdown-menu {
right: -50% !important;
}
}
}
.accountCheck {
color: $icon-color;
font-weight: $font-weight-normal;
}
.notificationsWrapper {
width: min-content;
}
.avatar {
display: flex;
align-items: center;
justify-content: center;
overflow: hidden;
height: 40px;
width: 40px;
background: $blue;
font-weight: 600;
font-size: 18px;
margin-right: 10px;
img {
height: 100%;
}
}
.badge {
display: flex;
align-items: center;
justify-content: center;
width: 22px;
height: 22px;
margin: auto 6px;
border-radius: 50%;
font-size: 12px;
font-weight: $font-weight-bold;
color: $main-background;
}
.burger {
align-self: end;
padding-left: 0;
}
.headerIcon {
fill: $icon-color;
}
.settingsIcon {
fill: $icon-blue;
}
.adminEmail {
color: #A5A7B8;
font-weight: $font-weight-normal;
font-size: 1rem;
}
.searchForm {
min-width: 255px;
}
.inputGroupText {
background: #12142B;
opacity: .8;
}

View File

@ -0,0 +1,6 @@
{
"name": "Header",
"version": "0.0.0",
"private": true,
"main": "./Header.js"
}

View File

@ -0,0 +1,115 @@
import React, { useState } from 'react';
import cx from 'classnames';
import { Button } from 'reactstrap';
import { useDispatch } from 'react-redux';
import {
changeThemeColor
} from '../../actions/layout';
import CustomColorPicker from '../ColorPicker';
import config from '../../config';
import Widget from '../Widget';
import s from './Helper.module.scss'; // eslint-disable-line
const Helper = () => {
const dispatch = useDispatch();
const [isOpened, setIsOpened] = useState(false);
const themeColor = localStorage.getItem("themeColor");
const toggle = () => {
setIsOpened((prevState) => !prevState);
};
const updateColor = (value) => {
localStorage.setItem("themeColor", value);
dispatch(changeThemeColor(value));
};
return (
<div className={cx(s.themeHelper, { [s.themeHelperOpened]: isOpened })}>
<div className={`${s.themeHelperBtn} bg-primary helper-button`} onClick={toggle}>
<div className={cx(s.themeHelperSpinner, 'text-white')}>
<i className="la la-cog" />
<i className="la la-cog" />
</div>
</div>
<Widget
className={s.themeHelperContent}
>
<div className={s.helperHeader}>
<h5 className="m-0">Theme</h5>
</div>
<div className="theme-settings">
<h5 className="mt-4 navbar-color-picker">Theme Color</h5>
<CustomColorPicker
colors={config.app.colors}
activeColor={themeColor}
updateColor={updateColor}
customizationItem={"navbar"}
/>
</div>
<div className="d-grid mt-5">
<Button
href="https://flatlogic.com/templates/light-blue-react"
target="_blank"
className="btn-rounded-f btn-block fs-mini purchase-button"
color="info"
>
<span className="text-white">Purchase</span>
</Button>
<Button
href="https://demo.flatlogic.com/light-blue-react/documentation/getting-started/overview"
target="_blank"
className="btn-rounded-f btn-block fs-mini text-white mt-4"
color="primary"
>
Documentation
</Button>
</div>
<div className="d-flex justify-content-between mt-4">
<Button
href="https://flatlogic.com/forum"
target="_blank"
className="btn-default btn-rounded-f fs-mini text-white px-2"
>
<i className="glyphicon glyphicon-headphones me-1" />
Support
</Button>
<Button
href="https://github.com/flatlogic/light-blue-react-template"
target="_blank"
className="btn-default btn-rounded-f fs-mini text-white px-2"
>
<i className="fa fa-github me-1" />
Github
</Button>
</div>
<div className="mt-lg d-flex flex-column align-items-center theme-helper__sharing">
<span className="fs-sm">
Thank you for sharing!
</span>
<div className="d-flex justify-content-center text-light mt-2">
<a
target="_blank"
rel="noopener noreferrer"
href="https://twitter.com/intent/tweet?text=Amazing%20dashboard%20built%20with%20NodeJS,%20React%20and%20Bootstrap!&url=https://github.com/flatlogic/react-dashboard&via=flatlogic"
>
<i className="fa fa-twitter pe-1" />
</a>
<a
href="https://www.facebook.com/search/top/?q=flatlogic%20llc"
target="_blank"
rel="noopener noreferrer"
>
<i className="fa fa-facebook pl-1" />
</a>
</div>
</div>
</Widget>
</div>
);
};
export default Helper;

View File

@ -0,0 +1,185 @@
@import '../../styles/app';
.themeHelper {
width: $helper-width;
position: fixed;
right: -$helper-width;
top: 20px;
bottom: 20px;
z-index: 101;
.helperHeader {
display: flex;
justify-content: space-between;
align-items: center;
margin: 0 0 30px 0;
}
@include transition(right $sidebar-transition-time ease-in-out);
& :global {
.abc-radio-secondary input[type="radio"]:not(:checked)+label::before {
background-color: #798892;
}
.abc-radio {
& > label {
padding-left: 25px;
&:before, &:after {
outline: none !important;
transition: $transition-base;
margin-left: 4px;
}
}
}
.abc-radio-warning input[type="radio"]:not(:checked)+label::before {
background-color: theme-color('warning');
}
}
.themeSwitcher {
display: flex;
flex-direction: column;
align-items: center;
.theme {
position: relative;
&,
& > label {
width: 100%;
height: max-content;
}
& > input {
position: absolute;
width: 0;
height: 0;
padding: 0;
margin: 0;
pointer-events: none;
opacity: 0;
}
& > label {
margin: 0;
border: 1px solid $input-border-color;
padding: 3px;
border-radius: $border-radius;
transition: background-color .2s ease-in-out;
cursor: pointer;
display: block;
&:hover {
background-color: $gray-200;
}
}
& > input:checked + label {
background-color: $gray-300;
}
.themeImage {
width: 100%;
}
}
}
&.themeHelperOpened {
right: 0;
}
.themeHelperBtn {
position: absolute;
top: 7%;
right: unset;
margin-left: 20px;
width: $sidebar-width-open / 4;
transform: translateX(-76px);
margin-top: -($widget-padding-vertical);
cursor: pointer;
z-index: 0;
border-radius: 50% 0 0 50%;
padding: $spacer * 0.8 $spacer / 2 $spacer * 0.8 $spacer;
i {
animation-duration: 6500ms;
animation-iteration-count: infinite;
animation-timing-function: linear;
}
i:first-of-type {
animation-name: spin;
margin-right: -$spacer * 1.15;
vertical-align: text-bottom;
}
i:last-of-type {
animation-name: spin-reverse;
vertical-align: $font-size-sm;
}
}
.themeHelperSpinner {
font-size: $font-size-lg * 1.4;
line-height: initial;
}
.themeHelperHeader {
padding-top: 0;
h6 {
margin: auto;
}
}
.themeHelperContent {
background-color: theme-color(inverse);
border-radius: $border-radius 0 0 $border-radius;
overflow-y: scroll;
height: 100%;
&::-webkit-scrollbar {
width: 1em;
}
&::-webkit-scrollbar-track {
box-shadow: none;
}
&::-webkit-scrollbar-thumb {
background-color: #333;
outline: 1px solid #000;
}
}
.themeHelperSharing {
font-size: $font-size-lg;
cursor: pointer;
}
:global .glyphicon {
vertical-align: top;
}
@keyframes spin {
0% {
transform: rotate(0deg);
}
50% {
transform: rotate(360deg);
}
}
@keyframes spin-reverse {
0% {
transform: rotate(0deg);
}
50% {
transform: rotate(-360deg);
}
}
}

View File

@ -0,0 +1,6 @@
{
"name": "Helper",
"version": "0.0.0",
"private": true,
"main": "./Helper.js"
}

View File

@ -0,0 +1,15 @@
import React from 'react';
const ArrowIcon = (props) => (
<svg className={props.className} width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<path fillRule="evenodd" clipRule="evenodd" d="M3.33329 8.66668H11.2433L8.82129 11.5733C8.58529 11.856 8.62396 12.2767 8.90663 12.512C9.18996 12.748 9.60996 12.7093 9.84596 12.4267L13.1793 8.42668C13.2053 8.39534 13.218 8.35868 13.2373 8.32401C13.2533 8.29601 13.2726 8.27201 13.2846 8.24134C13.3146 8.16468 13.3326 8.08401 13.3326 8.00268C13.3326 8.00201 13.3333 8.00068 13.3333 8.00001C13.3333 7.99934 13.3326 7.99801 13.3326 7.99734C13.3326 7.91601 13.3146 7.83534 13.2846 7.75868C13.2726 7.72801 13.2533 7.70401 13.2373 7.67601C13.218 7.64134 13.2053 7.60468 13.1793 7.57334L9.84596 3.57334C9.71329 3.41534 9.52396 3.33334 9.33329 3.33334C9.18263 3.33334 9.03129 3.38401 8.90663 3.48801C8.62396 3.72334 8.58529 4.14401 8.82129 4.42668L11.2433 7.33334H3.33329C2.96529 7.33334 2.66663 7.63201 2.66663 8.00001C2.66663 8.36801 2.96529 8.66668 3.33329 8.66668Z" />
<mask id={props.maskName} mask-type="alpha" maskUnits="userSpaceOnUse" x="2" y="3" width="12" height="10">
<path fillRule="evenodd" clipRule="evenodd" d="M3.33329 8.66668H11.2433L8.82129 11.5733C8.58529 11.856 8.62396 12.2767 8.90663 12.512C9.18996 12.748 9.60996 12.7093 9.84596 12.4267L13.1793 8.42668C13.2053 8.39534 13.218 8.35868 13.2373 8.32401C13.2533 8.29601 13.2726 8.27201 13.2846 8.24134C13.3146 8.16468 13.3326 8.08401 13.3326 8.00268C13.3326 8.00201 13.3333 8.00068 13.3333 8.00001C13.3333 7.99934 13.3326 7.99801 13.3326 7.99734C13.3326 7.91601 13.3146 7.83534 13.2846 7.75868C13.2726 7.72801 13.2533 7.70401 13.2373 7.67601C13.218 7.64134 13.2053 7.60468 13.1793 7.57334L9.84596 3.57334C9.71329 3.41534 9.52396 3.33334 9.33329 3.33334C9.18263 3.33334 9.03129 3.38401 8.90663 3.48801C8.62396 3.72334 8.58529 4.14401 8.82129 4.42668L11.2433 7.33334H3.33329C2.96529 7.33334 2.66663 7.63201 2.66663 8.00001C2.66663 8.36801 2.96529 8.66668 3.33329 8.66668Z" />
</mask>
<g mask={`url(#${props.maskName})`}>
<rect width="16" height="16"/>
</g>
</svg>
);
export default ArrowIcon;

View File

@ -0,0 +1,15 @@
import React from 'react';
const BellIcon = (props) => (
<svg className={props.className} width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
<path fillRule="evenodd" clipRule="evenodd" d="M4.59538 13.3333L5.57872 12.3483C5.89372 12.0333 6.06705 11.615 6.06705 11.17V7.27248C6.06705 6.14165 6.55872 5.06082 7.41705 4.30915C8.28205 3.55082 9.38372 3.21748 10.5312 3.36832C12.4704 3.62582 13.9329 5.37915 13.9329 7.44748V11.17C13.9329 11.615 14.1062 12.0333 14.4204 12.3475L15.4045 13.3333H4.59538ZM11.6662 15.2842C11.6662 16.0333 10.9029 16.6667 9.99955 16.6667C9.09622 16.6667 8.33288 16.0333 8.33288 15.2842V15H11.6662V15.2842ZM17.1004 12.6733L15.5995 11.17V7.44748C15.5995 4.54665 13.5145 2.08248 10.7495 1.71665C9.14788 1.50332 7.53121 1.99248 6.31871 3.05582C5.09871 4.12415 4.40038 5.66082 4.40038 7.27248L4.39955 11.17L2.89871 12.6733C2.50788 13.065 2.39205 13.6475 2.60371 14.1583C2.81621 14.67 3.31038 15 3.86371 15H6.66621V15.2842C6.66621 16.9658 8.16121 18.3333 9.99955 18.3333C11.8379 18.3333 13.3329 16.9658 13.3329 15.2842V15H16.1354C16.6887 15 17.182 14.67 17.3937 14.1591C17.6062 13.6475 17.4912 13.0641 17.1004 12.6733Z" />
<mask id="bell" mask-type="alpha" maskUnits="userSpaceOnUse" x="2" y="1" width="16" height="18">
<path fillRule="evenodd" clipRule="evenodd" d="M4.59538 13.3333L5.57872 12.3483C5.89372 12.0333 6.06705 11.615 6.06705 11.17V7.27248C6.06705 6.14165 6.55872 5.06082 7.41705 4.30915C8.28205 3.55082 9.38372 3.21748 10.5312 3.36832C12.4704 3.62582 13.9329 5.37915 13.9329 7.44748V11.17C13.9329 11.615 14.1062 12.0333 14.4204 12.3475L15.4045 13.3333H4.59538ZM11.6662 15.2842C11.6662 16.0333 10.9029 16.6667 9.99955 16.6667C9.09622 16.6667 8.33288 16.0333 8.33288 15.2842V15H11.6662V15.2842ZM17.1004 12.6733L15.5995 11.17V7.44748C15.5995 4.54665 13.5145 2.08248 10.7495 1.71665C9.14788 1.50332 7.53121 1.99248 6.31871 3.05582C5.09871 4.12415 4.40038 5.66082 4.40038 7.27248L4.39955 11.17L2.89871 12.6733C2.50788 13.065 2.39205 13.6475 2.60371 14.1583C2.81621 14.67 3.31038 15 3.86371 15H6.66621V15.2842C6.66621 16.9658 8.16121 18.3333 9.99955 18.3333C11.8379 18.3333 13.3329 16.9658 13.3329 15.2842V15H16.1354C16.6887 15 17.182 14.67 17.3937 14.1591C17.6062 13.6475 17.4912 13.0641 17.1004 12.6733Z" />
</mask>
<g mask="url(#bell)">
<rect width="20" height="20" />
</g>
</svg>
);
export default BellIcon;

View File

@ -0,0 +1,15 @@
import React from 'react';
const BurgerIcon = (props) => (
<svg className={props.className} width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
<path fillRule="evenodd" clipRule="evenodd" d="M3.29024 5H16.7094C17.1444 5 17.5002 5.35583 17.5002 5.79083V5.87583C17.5002 6.31083 17.1444 6.66667 16.7094 6.66667H3.29024C2.85524 6.66667 2.50024 6.31083 2.50024 5.87583V5.79083C2.50024 5.35583 2.85524 5 3.29024 5ZM16.7094 9.16667H3.29024C2.85524 9.16667 2.50024 9.5225 2.50024 9.9575V10.0425C2.50024 10.4775 2.85524 10.8333 3.29024 10.8333H16.7094C17.1444 10.8333 17.5002 10.4775 17.5002 10.0425V9.9575C17.5002 9.5225 17.1444 9.16667 16.7094 9.16667ZM16.7094 13.3333H3.29024C2.85524 13.3333 2.50024 13.6892 2.50024 14.1242V14.2092C2.50024 14.6442 2.85524 15 3.29024 15H16.7094C17.1444 15 17.5002 14.6442 17.5002 14.2092V14.1242C17.5002 13.6892 17.1444 13.3333 16.7094 13.3333Z" />
<mask id="burger" mask-type="alpha" maskUnits="userSpaceOnUse" x="2" y="5" width="16" height="10">
<path fillRule="evenodd" clipRule="evenodd" d="M3.29024 5H16.7094C17.1444 5 17.5002 5.35583 17.5002 5.79083V5.87583C17.5002 6.31083 17.1444 6.66667 16.7094 6.66667H3.29024C2.85524 6.66667 2.50024 6.31083 2.50024 5.87583V5.79083C2.50024 5.35583 2.85524 5 3.29024 5ZM16.7094 9.16667H3.29024C2.85524 9.16667 2.50024 9.5225 2.50024 9.9575V10.0425C2.50024 10.4775 2.85524 10.8333 3.29024 10.8333H16.7094C17.1444 10.8333 17.5002 10.4775 17.5002 10.0425V9.9575C17.5002 9.5225 17.1444 9.16667 16.7094 9.16667ZM16.7094 13.3333H3.29024C2.85524 13.3333 2.50024 13.6892 2.50024 14.1242V14.2092C2.50024 14.6442 2.85524 15 3.29024 15H16.7094C17.1444 15 17.5002 14.6442 17.5002 14.2092V14.1242C17.5002 13.6892 17.1444 13.3333 16.7094 13.3333Z" />
</mask>
<g mask="url(#burger)">
<rect width="20" height="20" />
</g>
</svg>
);
export default BurgerIcon;

View File

@ -0,0 +1,15 @@
import React from 'react';
const MessageIcon = (props) => (
<svg className={props.className} width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
<path fillRule="evenodd" clipRule="evenodd" d="M5.83346 9.16604C5.83346 8.70604 6.20679 8.33271 6.66679 8.33271C7.12679 8.33271 7.50013 8.70604 7.50013 9.16604C7.50013 9.62604 7.12679 9.99937 6.66679 9.99937C6.20679 9.99937 5.83346 9.62604 5.83346 9.16604ZM10.0001 8.33271C9.54013 8.33271 9.16679 8.70604 9.16679 9.16604C9.16679 9.62604 9.54013 9.99937 10.0001 9.99937C10.4601 9.99937 10.8335 9.62604 10.8335 9.16604C10.8335 8.70604 10.4601 8.33271 10.0001 8.33271ZM13.3335 8.33271C12.8735 8.33271 12.5001 8.70604 12.5001 9.16604C12.5001 9.62604 12.8735 9.99937 13.3335 9.99937C13.7935 9.99937 14.1668 9.62604 14.1668 9.16604C14.1668 8.70604 13.7935 8.33271 13.3335 8.33271ZM16.5821 10.2451C16.1596 12.9568 13.9738 15.206 11.2663 15.7135C9.95879 15.9601 8.62713 15.8193 7.41879 15.3076C7.07629 15.1626 6.72213 15.0893 6.37463 15.0893C6.21629 15.0893 6.05963 15.1043 5.90546 15.1351L3.56213 15.6035L4.03129 13.256C4.12963 12.7685 4.06963 12.2468 3.85879 11.7476C3.34713 10.5393 3.20713 9.20845 3.45296 7.90012C3.96046 5.19262 6.20879 3.00679 8.92129 2.58429C11.0796 2.24845 13.1905 2.92845 14.7138 4.45179C16.238 5.97595 16.9188 8.08762 16.5821 10.2451ZM15.893 3.27346C13.9888 1.37012 11.3555 0.520956 8.66463 0.936789C5.26713 1.46679 2.45046 4.20346 1.81463 7.59262C1.50796 9.22429 1.68463 10.886 2.32379 12.3968C2.40463 12.5893 2.42963 12.7685 2.39796 12.9293L1.68296 16.5026C1.62796 16.776 1.71379 17.0585 1.91129 17.2551C2.06879 17.4135 2.28129 17.4993 2.50046 17.4993C2.55463 17.4993 2.60879 17.4943 2.66379 17.4835L6.23296 16.7693C6.43796 16.7301 6.63629 16.7876 6.76879 16.8426C8.28129 17.4818 9.94296 17.6576 11.573 17.3518C14.963 16.716 17.6996 13.8993 18.2296 10.5018C18.648 7.81262 17.7971 5.17762 15.893 3.27346Z" />
<mask id="message" mask-type="alpha" maskUnits="userSpaceOnUse" x="1" y="0" width="18" height="18">
<path fillRule="evenodd" clipRule="evenodd" d="M5.83346 9.16604C5.83346 8.70604 6.20679 8.33271 6.66679 8.33271C7.12679 8.33271 7.50013 8.70604 7.50013 9.16604C7.50013 9.62604 7.12679 9.99937 6.66679 9.99937C6.20679 9.99937 5.83346 9.62604 5.83346 9.16604ZM10.0001 8.33271C9.54013 8.33271 9.16679 8.70604 9.16679 9.16604C9.16679 9.62604 9.54013 9.99937 10.0001 9.99937C10.4601 9.99937 10.8335 9.62604 10.8335 9.16604C10.8335 8.70604 10.4601 8.33271 10.0001 8.33271ZM13.3335 8.33271C12.8735 8.33271 12.5001 8.70604 12.5001 9.16604C12.5001 9.62604 12.8735 9.99937 13.3335 9.99937C13.7935 9.99937 14.1668 9.62604 14.1668 9.16604C14.1668 8.70604 13.7935 8.33271 13.3335 8.33271ZM16.5821 10.2451C16.1596 12.9568 13.9738 15.206 11.2663 15.7135C9.95879 15.9601 8.62713 15.8193 7.41879 15.3076C7.07629 15.1626 6.72213 15.0893 6.37463 15.0893C6.21629 15.0893 6.05963 15.1043 5.90546 15.1351L3.56213 15.6035L4.03129 13.256C4.12963 12.7685 4.06963 12.2468 3.85879 11.7476C3.34713 10.5393 3.20713 9.20845 3.45296 7.90012C3.96046 5.19262 6.20879 3.00679 8.92129 2.58429C11.0796 2.24845 13.1905 2.92845 14.7138 4.45179C16.238 5.97595 16.9188 8.08762 16.5821 10.2451ZM15.893 3.27346C13.9888 1.37012 11.3555 0.520956 8.66463 0.936789C5.26713 1.46679 2.45046 4.20346 1.81463 7.59262C1.50796 9.22429 1.68463 10.886 2.32379 12.3968C2.40463 12.5893 2.42963 12.7685 2.39796 12.9293L1.68296 16.5026C1.62796 16.776 1.71379 17.0585 1.91129 17.2551C2.06879 17.4135 2.28129 17.4993 2.50046 17.4993C2.55463 17.4993 2.60879 17.4943 2.66379 17.4835L6.23296 16.7693C6.43796 16.7301 6.63629 16.7876 6.76879 16.8426C8.28129 17.4818 9.94296 17.6576 11.573 17.3518C14.963 16.716 17.6996 13.8993 18.2296 10.5018C18.648 7.81262 17.7971 5.17762 15.893 3.27346Z" />
</mask>
<g mask="url(#message)">
<rect width="20" height="20" />
</g>
</svg>
);
export default MessageIcon;

View File

@ -0,0 +1,15 @@
import React from 'react';
const PowerIcon = (props) => (
<svg className={props.className} width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
<path fillRule="evenodd" clipRule="evenodd" d="M10.8333 9.99998C10.8333 10.4608 10.4599 10.8333 9.99992 10.8333C9.53992 10.8333 9.16658 10.4608 9.16658 9.99998V1.66665C9.16658 1.20581 9.53992 0.833313 9.99992 0.833313C10.4599 0.833313 10.8333 1.20581 10.8333 1.66665V9.99998ZM12.699 2.95106C12.9098 2.54189 13.4132 2.38273 13.8215 2.59273C16.604 4.03189 18.3332 6.86939 18.3332 10.0002C18.3332 14.5944 14.5948 18.3336 9.99984 18.3336C5.40484 18.3336 1.6665 14.5944 1.6665 10.0002C1.6665 6.86939 3.39567 4.03189 6.179 2.59273C6.5865 2.38189 7.08984 2.54106 7.3015 2.95106C7.51317 3.35939 7.35234 3.86189 6.944 4.07356C4.7165 5.22439 3.33317 7.49523 3.33317 10.0002C3.33317 13.6761 6.324 16.6669 9.99984 16.6669C13.6757 16.6669 16.6665 13.6761 16.6665 10.0002C16.6665 7.49523 15.2832 5.22439 13.0565 4.07356C12.6473 3.86189 12.4873 3.35939 12.699 2.95106Z" />
<mask id="power" mask-type="alpha" maskUnits="userSpaceOnUse" x="1" y="0" width="18" height="19">
<path fillRule="evenodd" clipRule="evenodd" d="M10.8333 9.99998C10.8333 10.4608 10.4599 10.8333 9.99992 10.8333C9.53992 10.8333 9.16658 10.4608 9.16658 9.99998V1.66665C9.16658 1.20581 9.53992 0.833313 9.99992 0.833313C10.4599 0.833313 10.8333 1.20581 10.8333 1.66665V9.99998ZM12.699 2.95106C12.9098 2.54189 13.4132 2.38273 13.8215 2.59273C16.604 4.03189 18.3332 6.86939 18.3332 10.0002C18.3332 14.5944 14.5948 18.3336 9.99984 18.3336C5.40484 18.3336 1.6665 14.5944 1.6665 10.0002C1.6665 6.86939 3.39567 4.03189 6.179 2.59273C6.5865 2.38189 7.08984 2.54106 7.3015 2.95106C7.51317 3.35939 7.35234 3.86189 6.944 4.07356C4.7165 5.22439 3.33317 7.49523 3.33317 10.0002C3.33317 13.6761 6.324 16.6669 9.99984 16.6669C13.6757 16.6669 16.6665 13.6761 16.6665 10.0002C16.6665 7.49523 15.2832 5.22439 13.0565 4.07356C12.6473 3.86189 12.4873 3.35939 12.699 2.95106Z" />
</mask>
<g mask="url(#power)">
<rect width="20" height="20" />
</g>
</svg>
);
export default PowerIcon;

View File

@ -0,0 +1,15 @@
import React from 'react';
const SearchIcon = (props) => (
<svg className={props.className} width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
<path fillRule="evenodd" clipRule="evenodd" d="M4.16667 9.16667C4.16667 6.40917 6.40917 4.16667 9.16667 4.16667C11.9242 4.16667 14.1667 6.40917 14.1667 9.16667C14.1667 11.9242 11.9242 14.1667 9.16667 14.1667C6.40917 14.1667 4.16667 11.9242 4.16667 9.16667ZM17.2558 16.0775L14.4267 13.2475C15.3042 12.1192 15.8333 10.705 15.8333 9.16667C15.8333 5.49083 12.8425 2.5 9.16667 2.5C5.49083 2.5 2.5 5.49083 2.5 9.16667C2.5 12.8425 5.49083 15.8333 9.16667 15.8333C10.705 15.8333 12.1192 15.3042 13.2475 14.4267L16.0775 17.2558C16.24 17.4183 16.4533 17.5 16.6667 17.5C16.88 17.5 17.0933 17.4183 17.2558 17.2558C17.5817 16.93 17.5817 16.4033 17.2558 16.0775Z" />
<mask id={props.addId || "search"} mask-type="alpha" maskUnits="userSpaceOnUse" x="2" y="2" width="16" height="16">
<path fillRule="evenodd" clipRule="evenodd" d="M4.16667 9.16667C4.16667 6.40917 6.40917 4.16667 9.16667 4.16667C11.9242 4.16667 14.1667 6.40917 14.1667 9.16667C14.1667 11.9242 11.9242 14.1667 9.16667 14.1667C6.40917 14.1667 4.16667 11.9242 4.16667 9.16667ZM17.2558 16.0775L14.4267 13.2475C15.3042 12.1192 15.8333 10.705 15.8333 9.16667C15.8333 5.49083 12.8425 2.5 9.16667 2.5C5.49083 2.5 2.5 5.49083 2.5 9.16667C2.5 12.8425 5.49083 15.8333 9.16667 15.8333C10.705 15.8333 12.1192 15.3042 13.2475 14.4267L16.0775 17.2558C16.24 17.4183 16.4533 17.5 16.6667 17.5C16.88 17.5 17.0933 17.4183 17.2558 17.2558C17.5817 16.93 17.5817 16.4033 17.2558 16.0775Z" />
</mask>
<g mask={`url(#${props.addId || 'search'})`}>
<rect width="20" height="20" />
</g>
</svg>
);
export default SearchIcon;

View File

@ -0,0 +1,15 @@
import React from 'react';
const SettingsIcon = (props) => (
<svg className={props.className} width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
<path fillRule="evenodd" clipRule="evenodd" d="M3.66898 9.68508C4.59898 10.0042 5.33981 10.7826 5.64981 11.7692L5.68314 11.8692C6.03814 12.9159 5.89398 14.0426 5.29898 14.8876C5.19064 15.0409 5.21481 15.2242 5.32898 15.3109L7.05564 16.6226C7.11648 16.6684 7.17564 16.6684 7.21231 16.6642C7.25398 16.6576 7.31481 16.6351 7.36398 16.5651L7.55648 16.2917C8.13064 15.4776 9.05564 14.9751 10.0323 14.9467C11.129 14.9242 12.114 15.4267 12.7273 16.3126L12.8256 16.4551C12.8748 16.5251 12.9348 16.5484 12.9773 16.5551C13.014 16.5626 13.074 16.5601 13.134 16.5134L14.8515 15.2176C14.9715 15.1276 14.9981 14.9351 14.909 14.8059L14.6923 14.4934C14.134 13.6867 13.9681 12.6401 14.249 11.6942C14.554 10.6642 15.3298 9.84925 16.3256 9.51591L16.4931 9.45925C16.6273 9.41508 16.6998 9.24841 16.6523 9.09508L15.9965 6.99425C15.9656 6.89592 15.9023 6.85175 15.8673 6.83341C15.8173 6.80758 15.7631 6.80341 15.7115 6.82091L15.4281 6.91508C14.459 7.23758 13.3898 7.06258 12.569 6.44508L12.479 6.37758C11.699 5.79092 11.2348 4.84508 11.2381 3.84841L11.2398 3.61508C11.2398 3.50425 11.1873 3.43508 11.1556 3.40341C11.1256 3.37258 11.0748 3.33591 11.0031 3.33591L8.88064 3.33341C8.75064 3.33341 8.64481 3.45758 8.64398 3.61091L8.64314 3.81258C8.63898 4.82508 8.16481 5.78841 7.37481 6.39091L7.26731 6.47258C6.39814 7.13341 5.26481 7.32008 4.23814 6.97008C4.19898 6.95675 4.16231 6.95925 4.12731 6.97758C4.10064 6.99091 4.05231 7.02508 4.02898 7.10091L3.34814 9.26425C3.29898 9.42175 3.37981 9.58591 3.53231 9.63841L3.66898 9.68508ZM7.17814 18.3334C6.77314 18.3334 6.37981 18.2017 6.04814 17.9492L4.32148 16.6384C3.49648 16.0134 3.31398 14.8109 3.91398 13.9584C4.22564 13.5167 4.28981 12.9492 4.10648 12.4109L4.06064 12.2709C3.90814 11.7859 3.55981 11.4092 3.12898 11.2617H3.12814L2.99231 11.2142C1.97731 10.8667 1.43564 9.79091 1.75814 8.76425L2.43814 6.60175C2.59231 6.11258 2.92481 5.71758 3.37481 5.49008C3.81481 5.26841 4.31231 5.23425 4.77731 5.39341C5.27648 5.56341 5.83064 5.47091 6.25814 5.14591L6.36564 5.06425C6.74564 4.77425 6.97481 4.30341 6.97648 3.80591L6.97731 3.60508C6.98148 2.53508 7.83564 1.66675 8.87981 1.66675H8.88314L11.0056 1.66925C11.5073 1.67008 11.9806 1.86841 12.3373 2.22758C12.7065 2.59841 12.9081 3.09425 12.9065 3.62341L12.9048 3.85591C12.9031 4.32758 13.119 4.77341 13.4831 5.04675L13.5723 5.11425C13.9548 5.40175 14.4531 5.48425 14.9006 5.33425L15.1831 5.24008C15.664 5.08008 16.1756 5.11925 16.6265 5.35008C17.089 5.58675 17.4306 5.99425 17.5873 6.49841L18.2431 8.59925C18.5598 9.61425 18.0115 10.7092 17.0223 11.0401L16.8548 11.0959C16.3748 11.2576 15.9973 11.6576 15.8465 12.1676C15.7081 12.6351 15.7881 13.1492 16.0623 13.5442L16.279 13.8567C16.874 14.7167 16.684 15.9234 15.8556 16.5476L14.1381 17.8442C13.7256 18.1559 13.2198 18.2817 12.7123 18.2009C12.2006 18.1184 11.754 17.8351 11.4548 17.4034L11.3565 17.2601C11.0648 16.8401 10.5981 16.5851 10.109 16.6126C9.61898 16.6259 9.19564 16.8584 8.91898 17.2517L8.72648 17.5251C8.42481 17.9526 7.97731 18.2317 7.46814 18.3117C7.37064 18.3267 7.27398 18.3334 7.17814 18.3334ZM9.99998 8.75C9.31081 8.75 8.74998 9.31084 8.74998 10C8.74998 10.6892 9.31081 11.25 9.99998 11.25C10.6891 11.25 11.25 10.6892 11.25 10C11.25 9.31084 10.6891 8.75 9.99998 8.75ZM9.99998 12.9167C8.39164 12.9167 7.08331 11.6083 7.08331 10C7.08331 8.39167 8.39164 7.08333 9.99998 7.08333C11.6083 7.08333 12.9166 8.39167 12.9166 10C12.9166 11.6083 11.6083 12.9167 9.99998 12.9167Z" />
<mask id={props.addId || "settings"} mask-type="alpha" maskUnits="userSpaceOnUse" x="1" y="1" width="18" height="18">
<path fillRule="evenodd" clipRule="evenodd" d="M3.66898 9.68508C4.59898 10.0042 5.33981 10.7826 5.64981 11.7692L5.68314 11.8692C6.03814 12.9159 5.89398 14.0426 5.29898 14.8876C5.19064 15.0409 5.21481 15.2242 5.32898 15.3109L7.05564 16.6226C7.11648 16.6684 7.17564 16.6684 7.21231 16.6642C7.25398 16.6576 7.31481 16.6351 7.36398 16.5651L7.55648 16.2917C8.13064 15.4776 9.05564 14.9751 10.0323 14.9467C11.129 14.9242 12.114 15.4267 12.7273 16.3126L12.8256 16.4551C12.8748 16.5251 12.9348 16.5484 12.9773 16.5551C13.014 16.5626 13.074 16.5601 13.134 16.5134L14.8515 15.2176C14.9715 15.1276 14.9981 14.9351 14.909 14.8059L14.6923 14.4934C14.134 13.6867 13.9681 12.6401 14.249 11.6942C14.554 10.6642 15.3298 9.84925 16.3256 9.51591L16.4931 9.45925C16.6273 9.41508 16.6998 9.24841 16.6523 9.09508L15.9965 6.99425C15.9656 6.89592 15.9023 6.85175 15.8673 6.83341C15.8173 6.80758 15.7631 6.80341 15.7115 6.82091L15.4281 6.91508C14.459 7.23758 13.3898 7.06258 12.569 6.44508L12.479 6.37758C11.699 5.79092 11.2348 4.84508 11.2381 3.84841L11.2398 3.61508C11.2398 3.50425 11.1873 3.43508 11.1556 3.40341C11.1256 3.37258 11.0748 3.33591 11.0031 3.33591L8.88064 3.33341C8.75064 3.33341 8.64481 3.45758 8.64398 3.61091L8.64314 3.81258C8.63898 4.82508 8.16481 5.78841 7.37481 6.39091L7.26731 6.47258C6.39814 7.13341 5.26481 7.32008 4.23814 6.97008C4.19898 6.95675 4.16231 6.95925 4.12731 6.97758C4.10064 6.99091 4.05231 7.02508 4.02898 7.10091L3.34814 9.26425C3.29898 9.42175 3.37981 9.58591 3.53231 9.63841L3.66898 9.68508ZM7.17814 18.3334C6.77314 18.3334 6.37981 18.2017 6.04814 17.9492L4.32148 16.6384C3.49648 16.0134 3.31398 14.8109 3.91398 13.9584C4.22564 13.5167 4.28981 12.9492 4.10648 12.4109L4.06064 12.2709C3.90814 11.7859 3.55981 11.4092 3.12898 11.2617H3.12814L2.99231 11.2142C1.97731 10.8667 1.43564 9.79091 1.75814 8.76425L2.43814 6.60175C2.59231 6.11258 2.92481 5.71758 3.37481 5.49008C3.81481 5.26841 4.31231 5.23425 4.77731 5.39341C5.27648 5.56341 5.83064 5.47091 6.25814 5.14591L6.36564 5.06425C6.74564 4.77425 6.97481 4.30341 6.97648 3.80591L6.97731 3.60508C6.98148 2.53508 7.83564 1.66675 8.87981 1.66675H8.88314L11.0056 1.66925C11.5073 1.67008 11.9806 1.86841 12.3373 2.22758C12.7065 2.59841 12.9081 3.09425 12.9065 3.62341L12.9048 3.85591C12.9031 4.32758 13.119 4.77341 13.4831 5.04675L13.5723 5.11425C13.9548 5.40175 14.4531 5.48425 14.9006 5.33425L15.1831 5.24008C15.664 5.08008 16.1756 5.11925 16.6265 5.35008C17.089 5.58675 17.4306 5.99425 17.5873 6.49841L18.2431 8.59925C18.5598 9.61425 18.0115 10.7092 17.0223 11.0401L16.8548 11.0959C16.3748 11.2576 15.9973 11.6576 15.8465 12.1676C15.7081 12.6351 15.7881 13.1492 16.0623 13.5442L16.279 13.8567C16.874 14.7167 16.684 15.9234 15.8556 16.5476L14.1381 17.8442C13.7256 18.1559 13.2198 18.2817 12.7123 18.2009C12.2006 18.1184 11.754 17.8351 11.4548 17.4034L11.3565 17.2601C11.0648 16.8401 10.5981 16.5851 10.109 16.6126C9.61898 16.6259 9.19564 16.8584 8.91898 17.2517L8.72648 17.5251C8.42481 17.9526 7.97731 18.2317 7.46814 18.3117C7.37064 18.3267 7.27398 18.3334 7.17814 18.3334ZM9.99998 8.75C9.31081 8.75 8.74998 9.31084 8.74998 10C8.74998 10.6892 9.31081 11.25 9.99998 11.25C10.6891 11.25 11.25 10.6892 11.25 10C11.25 9.31084 10.6891 8.75 9.99998 8.75ZM9.99998 12.9167C8.39164 12.9167 7.08331 11.6083 7.08331 10C7.08331 8.39167 8.39164 7.08333 9.99998 7.08333C11.6083 7.08333 12.9166 8.39167 12.9166 10C12.9166 11.6083 11.6083 12.9167 9.99998 12.9167Z" />
</mask>
<g mask={`url(#${props.addId || 'settings'})`}>
<rect width="20" height="20" />
</g>
</svg>
);
export default SettingsIcon;

View File

@ -0,0 +1,15 @@
import React from 'react';
const ChartsIcon = (props) => (
<svg className={props.className} width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
<path fillRule="evenodd" clipRule="evenodd" d="M17.3511 11.7146C16.9153 11.5596 16.4403 11.7871 16.2878 12.2221C15.3478 14.8805 12.8203 16.6663 10.0003 16.6663C6.32443 16.6663 3.3336 13.6763 3.3336 9.99962C3.3336 7.17962 5.11943 4.65212 7.77776 3.71212C8.21193 3.55962 8.43943 3.08379 8.2861 2.64962C8.13276 2.21629 7.65693 1.98796 7.22276 2.14212C3.89943 3.31629 1.66693 6.47379 1.66693 9.99962C1.66693 14.5946 5.40526 18.333 10.0003 18.333C13.5261 18.333 16.6836 16.1013 17.8586 12.7771C18.0119 12.3438 17.7853 11.868 17.3511 11.7146ZM11.6667 8.3333V3.39246C14.2175 3.75913 16.2408 5.78163 16.6075 8.3333H11.6667ZM10.8333 1.66663C10.3733 1.66663 10 2.03913 10 2.49996V9.16663C10 9.62746 10.3733 9.99996 10.8333 9.99996H17.5C17.96 9.99996 18.3333 9.62746 18.3333 9.16663C18.3333 5.03079 14.9683 1.66663 10.8333 1.66663Z" />
<mask id="charts" mask-type="alpha" maskUnits="userSpaceOnUse" x="1" y="1" width="18" height="18">
<path fillRule="evenodd" clipRule="evenodd" d="M17.3511 11.7146C16.9153 11.5596 16.4403 11.7871 16.2878 12.2221C15.3478 14.8805 12.8203 16.6663 10.0003 16.6663C6.32443 16.6663 3.3336 13.6763 3.3336 9.99962C3.3336 7.17962 5.11943 4.65212 7.77776 3.71212C8.21193 3.55962 8.43943 3.08379 8.2861 2.64962C8.13276 2.21629 7.65693 1.98796 7.22276 2.14212C3.89943 3.31629 1.66693 6.47379 1.66693 9.99962C1.66693 14.5946 5.40526 18.333 10.0003 18.333C13.5261 18.333 16.6836 16.1013 17.8586 12.7771C18.0119 12.3438 17.7853 11.868 17.3511 11.7146ZM11.6667 8.3333V3.39246C14.2175 3.75913 16.2408 5.78163 16.6075 8.3333H11.6667ZM10.8333 1.66663C10.3733 1.66663 10 2.03913 10 2.49996V9.16663C10 9.62746 10.3733 9.99996 10.8333 9.99996H17.5C17.96 9.99996 18.3333 9.62746 18.3333 9.16663C18.3333 5.03079 14.9683 1.66663 10.8333 1.66663Z" />
</mask>
<g mask="url(#charts)">
<rect width="20" height="20" />
</g>
</svg>
);
export default ChartsIcon;

View File

@ -0,0 +1,15 @@
import React from 'react';
const CoreIcon = (props) => (
<svg className={props.className} width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fillRule="evenodd" clipRule="evenodd" d="M15.8334 16.6666C15.3725 16.6666 15 16.2941 15 15.8333C15 15.3725 15.3725 15 15.8334 15C16.2942 15 16.6667 15.3725 16.6667 15.8333C16.6667 16.2941 16.2942 16.6666 15.8334 16.6666ZM15.8334 13.3333C14.455 13.3333 13.3334 14.455 13.3334 15.8333C13.3334 17.2116 14.455 18.3333 15.8334 18.3333C17.2117 18.3333 18.3334 17.2116 18.3334 15.8333C18.3334 14.455 17.2117 13.3333 15.8334 13.3333ZM10 16.6666C9.53919 16.6666 9.16669 16.2941 9.16669 15.8333C9.16669 15.3725 9.53919 15 10 15C10.4609 15 10.8334 15.3725 10.8334 15.8333C10.8334 16.2941 10.4609 16.6666 10 16.6666ZM10 13.3333C8.62169 13.3333 7.50002 14.455 7.50002 15.8333C7.50002 17.2116 8.62169 18.3333 10 18.3333C11.3784 18.3333 12.5 17.2116 12.5 15.8333C12.5 14.455 11.3784 13.3333 10 13.3333ZM4.16669 16.6666C3.70585 16.6666 3.33335 16.2941 3.33335 15.8333C3.33335 15.3725 3.70585 15 4.16669 15C4.62752 15 5.00002 15.3725 5.00002 15.8333C5.00002 16.2941 4.62752 16.6666 4.16669 16.6666ZM4.16669 13.3333C2.78835 13.3333 1.66669 14.455 1.66669 15.8333C1.66669 17.2116 2.78835 18.3333 4.16669 18.3333C5.54502 18.3333 6.66669 17.2116 6.66669 15.8333C6.66669 14.455 5.54502 13.3333 4.16669 13.3333ZM15.8334 10.8333C15.3725 10.8333 15 10.4608 15 9.99996C15 9.53913 15.3725 9.16663 15.8334 9.16663C16.2942 9.16663 16.6667 9.53913 16.6667 9.99996C16.6667 10.4608 16.2942 10.8333 15.8334 10.8333ZM15.8334 7.49996C14.455 7.49996 13.3334 8.62163 13.3334 9.99996C13.3334 11.3783 14.455 12.5 15.8334 12.5C17.2117 12.5 18.3334 11.3783 18.3334 9.99996C18.3334 8.62163 17.2117 7.49996 15.8334 7.49996ZM10 10.8333C9.53919 10.8333 9.16669 10.4608 9.16669 9.99996C9.16669 9.53913 9.53919 9.16663 10 9.16663C10.4609 9.16663 10.8334 9.53913 10.8334 9.99996C10.8334 10.4608 10.4609 10.8333 10 10.8333ZM10 7.49996C8.62169 7.49996 7.50002 8.62163 7.50002 9.99996C7.50002 11.3783 8.62169 12.5 10 12.5C11.3784 12.5 12.5 11.3783 12.5 9.99996C12.5 8.62163 11.3784 7.49996 10 7.49996ZM4.16669 10.8333C3.70585 10.8333 3.33335 10.4608 3.33335 9.99996C3.33335 9.53913 3.70585 9.16663 4.16669 9.16663C4.62752 9.16663 5.00002 9.53913 5.00002 9.99996C5.00002 10.4608 4.62752 10.8333 4.16669 10.8333ZM4.16669 7.49996C2.78835 7.49996 1.66669 8.62163 1.66669 9.99996C1.66669 11.3783 2.78835 12.5 4.16669 12.5C5.54502 12.5 6.66669 11.3783 6.66669 9.99996C6.66669 8.62163 5.54502 7.49996 4.16669 7.49996ZM15.8334 3.33329C16.2942 3.33329 16.6667 3.70579 16.6667 4.16663C16.6667 4.62746 16.2942 4.99996 15.8334 4.99996C15.3725 4.99996 15 4.62746 15 4.16663C15 3.70579 15.3725 3.33329 15.8334 3.33329ZM15.8334 6.66663C17.2117 6.66663 18.3334 5.54496 18.3334 4.16663C18.3334 2.78829 17.2117 1.66663 15.8334 1.66663C14.455 1.66663 13.3334 2.78829 13.3334 4.16663C13.3334 5.54496 14.455 6.66663 15.8334 6.66663ZM10 4.99996C9.53919 4.99996 9.16669 4.62663 9.16669 4.16663C9.16669 3.70579 9.53919 3.33329 10 3.33329C10.4609 3.33329 10.8334 3.70579 10.8334 4.16663C10.8334 4.62663 10.4609 4.99996 10 4.99996ZM10 1.66663C8.62169 1.66663 7.50002 2.78829 7.50002 4.16663C7.50002 5.54496 8.62169 6.66663 10 6.66663C11.3784 6.66663 12.5 5.54496 12.5 4.16663C12.5 2.78829 11.3784 1.66663 10 1.66663ZM4.16669 4.99996C3.70585 4.99996 3.33335 4.62746 3.33335 4.16663C3.33335 3.70579 3.70585 3.33329 4.16669 3.33329C4.62752 3.33329 5.00002 3.70579 5.00002 4.16663C5.00002 4.62746 4.62752 4.99996 4.16669 4.99996ZM4.16669 1.66663C2.78835 1.66663 1.66669 2.78829 1.66669 4.16663C1.66669 5.54496 2.78835 6.66663 4.16669 6.66663C5.54502 6.66663 6.66669 5.54496 6.66669 4.16663C6.66669 2.78829 5.54502 1.66663 4.16669 1.66663Z" />
<mask id="core" mask-type="alpha" maskUnits="userSpaceOnUse" x="1" y="1" width="18" height="18">
<path fillRule="evenodd" clipRule="evenodd" d="M15.8334 16.6666C15.3725 16.6666 15 16.2941 15 15.8333C15 15.3725 15.3725 15 15.8334 15C16.2942 15 16.6667 15.3725 16.6667 15.8333C16.6667 16.2941 16.2942 16.6666 15.8334 16.6666ZM15.8334 13.3333C14.455 13.3333 13.3334 14.455 13.3334 15.8333C13.3334 17.2116 14.455 18.3333 15.8334 18.3333C17.2117 18.3333 18.3334 17.2116 18.3334 15.8333C18.3334 14.455 17.2117 13.3333 15.8334 13.3333ZM10 16.6666C9.53919 16.6666 9.16669 16.2941 9.16669 15.8333C9.16669 15.3725 9.53919 15 10 15C10.4609 15 10.8334 15.3725 10.8334 15.8333C10.8334 16.2941 10.4609 16.6666 10 16.6666ZM10 13.3333C8.62169 13.3333 7.50002 14.455 7.50002 15.8333C7.50002 17.2116 8.62169 18.3333 10 18.3333C11.3784 18.3333 12.5 17.2116 12.5 15.8333C12.5 14.455 11.3784 13.3333 10 13.3333ZM4.16669 16.6666C3.70585 16.6666 3.33335 16.2941 3.33335 15.8333C3.33335 15.3725 3.70585 15 4.16669 15C4.62752 15 5.00002 15.3725 5.00002 15.8333C5.00002 16.2941 4.62752 16.6666 4.16669 16.6666ZM4.16669 13.3333C2.78835 13.3333 1.66669 14.455 1.66669 15.8333C1.66669 17.2116 2.78835 18.3333 4.16669 18.3333C5.54502 18.3333 6.66669 17.2116 6.66669 15.8333C6.66669 14.455 5.54502 13.3333 4.16669 13.3333ZM15.8334 10.8333C15.3725 10.8333 15 10.4608 15 9.99996C15 9.53913 15.3725 9.16663 15.8334 9.16663C16.2942 9.16663 16.6667 9.53913 16.6667 9.99996C16.6667 10.4608 16.2942 10.8333 15.8334 10.8333ZM15.8334 7.49996C14.455 7.49996 13.3334 8.62163 13.3334 9.99996C13.3334 11.3783 14.455 12.5 15.8334 12.5C17.2117 12.5 18.3334 11.3783 18.3334 9.99996C18.3334 8.62163 17.2117 7.49996 15.8334 7.49996ZM10 10.8333C9.53919 10.8333 9.16669 10.4608 9.16669 9.99996C9.16669 9.53913 9.53919 9.16663 10 9.16663C10.4609 9.16663 10.8334 9.53913 10.8334 9.99996C10.8334 10.4608 10.4609 10.8333 10 10.8333ZM10 7.49996C8.62169 7.49996 7.50002 8.62163 7.50002 9.99996C7.50002 11.3783 8.62169 12.5 10 12.5C11.3784 12.5 12.5 11.3783 12.5 9.99996C12.5 8.62163 11.3784 7.49996 10 7.49996ZM4.16669 10.8333C3.70585 10.8333 3.33335 10.4608 3.33335 9.99996C3.33335 9.53913 3.70585 9.16663 4.16669 9.16663C4.62752 9.16663 5.00002 9.53913 5.00002 9.99996C5.00002 10.4608 4.62752 10.8333 4.16669 10.8333ZM4.16669 7.49996C2.78835 7.49996 1.66669 8.62163 1.66669 9.99996C1.66669 11.3783 2.78835 12.5 4.16669 12.5C5.54502 12.5 6.66669 11.3783 6.66669 9.99996C6.66669 8.62163 5.54502 7.49996 4.16669 7.49996ZM15.8334 3.33329C16.2942 3.33329 16.6667 3.70579 16.6667 4.16663C16.6667 4.62746 16.2942 4.99996 15.8334 4.99996C15.3725 4.99996 15 4.62746 15 4.16663C15 3.70579 15.3725 3.33329 15.8334 3.33329ZM15.8334 6.66663C17.2117 6.66663 18.3334 5.54496 18.3334 4.16663C18.3334 2.78829 17.2117 1.66663 15.8334 1.66663C14.455 1.66663 13.3334 2.78829 13.3334 4.16663C13.3334 5.54496 14.455 6.66663 15.8334 6.66663ZM10 4.99996C9.53919 4.99996 9.16669 4.62663 9.16669 4.16663C9.16669 3.70579 9.53919 3.33329 10 3.33329C10.4609 3.33329 10.8334 3.70579 10.8334 4.16663C10.8334 4.62663 10.4609 4.99996 10 4.99996ZM10 1.66663C8.62169 1.66663 7.50002 2.78829 7.50002 4.16663C7.50002 5.54496 8.62169 6.66663 10 6.66663C11.3784 6.66663 12.5 5.54496 12.5 4.16663C12.5 2.78829 11.3784 1.66663 10 1.66663ZM4.16669 4.99996C3.70585 4.99996 3.33335 4.62746 3.33335 4.16663C3.33335 3.70579 3.70585 3.33329 4.16669 3.33329C4.62752 3.33329 5.00002 3.70579 5.00002 4.16663C5.00002 4.62746 4.62752 4.99996 4.16669 4.99996ZM4.16669 1.66663C2.78835 1.66663 1.66669 2.78829 1.66669 4.16663C1.66669 5.54496 2.78835 6.66663 4.16669 6.66663C5.54502 6.66663 6.66669 5.54496 6.66669 4.16663C6.66669 2.78829 5.54502 1.66663 4.16669 1.66663Z" />
</mask>
<g mask="url(#core)">
<rect width="20" height="20" />
</g>
</svg>
);
export default CoreIcon;

View File

@ -0,0 +1,15 @@
import React from 'react';
const DashboardIcon = (props) => (
<svg className={props.className} width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
<path fillRule="evenodd" clipRule="evenodd" d="M15.8252 16.6667H13.3335V10.8333C13.3335 10.3725 12.9602 10 12.5002 10H7.50018C7.03935 10 6.66685 10.3725 6.66685 10.8333V16.6667H4.16685L4.17185 9.65251L9.99852 3.69334L15.8335 9.68667L15.8252 16.6667ZM8.33352 16.6667H11.6668V11.6667H8.33352V16.6667ZM17.0202 8.4875L10.596 1.9175C10.2818 1.59667 9.71852 1.59667 9.40435 1.9175L2.97935 8.48834C2.67518 8.80084 2.50018 9.2375 2.50018 9.68667V16.6667C2.50018 17.5858 3.20602 18.3333 4.07352 18.3333H7.50018H12.5002H15.926C16.7935 18.3333 17.5002 17.5858 17.5002 16.6667V9.68667C17.5002 9.2375 17.3252 8.80084 17.0202 8.4875Z" />
<mask id="dashboard" mask-type="alpha" maskUnits="userSpaceOnUse" x="2" y="1" width="16" height="18">
<path fillRule="evenodd" clipRule="evenodd" d="M15.8252 16.6667H13.3335V10.8333C13.3335 10.3725 12.9602 10 12.5002 10H7.50018C7.03935 10 6.66685 10.3725 6.66685 10.8333V16.6667H4.16685L4.17185 9.65251L9.99852 3.69334L15.8335 9.68667L15.8252 16.6667ZM8.33352 16.6667H11.6668V11.6667H8.33352V16.6667ZM17.0202 8.4875L10.596 1.9175C10.2818 1.59667 9.71852 1.59667 9.40435 1.9175L2.97935 8.48834C2.67518 8.80084 2.50018 9.2375 2.50018 9.68667V16.6667C2.50018 17.5858 3.20602 18.3333 4.07352 18.3333H7.50018H12.5002H15.926C16.7935 18.3333 17.5002 17.5858 17.5002 16.6667V9.68667C17.5002 9.2375 17.3252 8.80084 17.0202 8.4875Z" />
</mask>
<g mask="url(#dashboard)">
<rect width="20" height="20" />
</g>
</svg>
);
export default DashboardIcon;

View File

@ -0,0 +1,17 @@
import React from 'react';
const DocumentationIcon = (props) => (
<svg className={props.className} width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
<path fillRule="evenodd" clipRule="evenodd" d="M9.99998 11.6667H7.49998C7.03998 11.6667 6.66664 11.2933 6.66664 10.8333C6.66664 10.3733 7.03998 10 7.49998 10H9.99998C10.46 10 10.8333 10.3733 10.8333 10.8333C10.8333 11.2933 10.46 11.6667 9.99998 11.6667ZM6.66664 14.1667C6.66664 13.7067 7.03998 13.3333 7.49998 13.3333H12.5C12.9608 13.3333 13.3333 13.7067 13.3333 14.1667C13.3333 14.6267 12.9608 15 12.5 15H7.49998C7.03998 15 6.66664 14.6267 6.66664 14.1667ZM14.5369 16.6667H5.46272C5.20772 16.6667 5.00022 16.48 5.00022 16.25V3.75C5.00022 3.52 5.20772 3.33333 5.46272 3.33333H10.0002V5.95833C10.0002 7.26833 11.0144 8.33333 12.2619 8.33333H15.0002V16.25C15.0002 16.48 14.7927 16.6667 14.5369 16.6667ZM11.6669 4.14833L13.9519 6.66666H12.2619C11.9336 6.66666 11.6669 6.34916 11.6669 5.95833V4.14833ZM16.4502 6.94L11.9136 1.94C11.7552 1.76583 11.5319 1.66667 11.2961 1.66667H5.46272C4.28856 1.66667 3.33356 2.60167 3.33356 3.75V16.25C3.33356 17.3983 4.28856 18.3333 5.46272 18.3333H14.5369C15.7111 18.3333 16.6669 17.3983 16.6669 16.25V7.5C16.6669 7.2925 16.5894 7.09334 16.4502 6.94Z"/>
<mask id="documentation" mask-type="alpha" maskUnits="userSpaceOnUse" x="3" y="1" width="14" height="18">
<path fillRule="evenodd" clipRule="evenodd" d="M9.99998 11.6667H7.49998C7.03998 11.6667 6.66664 11.2933 6.66664 10.8333C6.66664 10.3733 7.03998 10 7.49998 10H9.99998C10.46 10 10.8333 10.3733 10.8333 10.8333C10.8333 11.2933 10.46 11.6667 9.99998 11.6667ZM6.66664 14.1667C6.66664 13.7067 7.03998 13.3333 7.49998 13.3333H12.5C12.9608 13.3333 13.3333 13.7067 13.3333 14.1667C13.3333 14.6267 12.9608 15 12.5 15H7.49998C7.03998 15 6.66664 14.6267 6.66664 14.1667ZM14.5369 16.6667H5.46272C5.20772 16.6667 5.00022 16.48 5.00022 16.25V3.75C5.00022 3.52 5.20772 3.33333 5.46272 3.33333H10.0002V5.95833C10.0002 7.26833 11.0144 8.33333 12.2619 8.33333H15.0002V16.25C15.0002 16.48 14.7927 16.6667 14.5369 16.6667ZM11.6669 4.14833L13.9519 6.66666H12.2619C11.9336 6.66666 11.6669 6.34916 11.6669 5.95833V4.14833ZM16.4502 6.94L11.9136 1.94C11.7552 1.76583 11.5319 1.66667 11.2961 1.66667H5.46272C4.28856 1.66667 3.33356 2.60167 3.33356 3.75V16.25C3.33356 17.3983 4.28856 18.3333 5.46272 18.3333H14.5369C15.7111 18.3333 16.6669 17.3983 16.6669 16.25V7.5C16.6669 7.2925 16.5894 7.09334 16.4502 6.94Z"/>
</mask>
<g mask="url(#documentation)">
<rect width="20" height="20"/>
</g>
</svg>
);
export default DocumentationIcon;

View File

@ -0,0 +1,15 @@
import React from 'react';
const UserIcon = (props) => (
<svg className={props.className} width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fillRule="evenodd" clipRule="evenodd" d="M12.5 9.16667C12.0392 9.16667 11.6667 9.54 11.6667 10C11.6667 10.9192 10.9192 11.6667 10 11.6667C9.08083 11.6667 8.33333 10.9192 8.33333 10C8.33333 9.54 7.96083 9.16667 7.5 9.16667C7.03917 9.16667 6.66667 9.54 6.66667 10C6.66667 11.8383 8.16167 13.3333 10 13.3333C11.8383 13.3333 13.3333 11.8383 13.3333 10C13.3333 9.54 12.9608 9.16667 12.5 9.16667ZM15 15.8333H5C4.54 15.8333 4.16667 15.4592 4.16667 15V7.5H15.8333V15C15.8333 15.4592 15.46 15.8333 15 15.8333ZM6.7675 4.41083C6.92333 4.25583 7.1375 4.16667 7.35667 4.16667H12.6433C12.8625 4.16667 13.0767 4.25583 13.2325 4.41083L14.655 5.83333H5.345L6.7675 4.41083ZM16.7675 5.58917L14.4108 3.2325C13.9392 2.76 13.3108 2.5 12.6433 2.5H7.35667C6.68917 2.5 6.06083 2.76 5.58917 3.2325L3.2325 5.58917C2.76 6.06083 2.5 6.68917 2.5 7.3575V15C2.5 16.3783 3.62167 17.5 5 17.5H15C16.3783 17.5 17.5 16.3783 17.5 15V7.3575C17.5 6.68917 17.24 6.06083 16.7675 5.58917Z" />
<mask id="ecommerce" mask-type="alpha" maskUnits="userSpaceOnUse" x="2" y="2" width="16" height="16">
<path fillRule="evenodd" clipRule="evenodd" d="M12.5 9.16667C12.0392 9.16667 11.6667 9.54 11.6667 10C11.6667 10.9192 10.9192 11.6667 10 11.6667C9.08083 11.6667 8.33333 10.9192 8.33333 10C8.33333 9.54 7.96083 9.16667 7.5 9.16667C7.03917 9.16667 6.66667 9.54 6.66667 10C6.66667 11.8383 8.16167 13.3333 10 13.3333C11.8383 13.3333 13.3333 11.8383 13.3333 10C13.3333 9.54 12.9608 9.16667 12.5 9.16667ZM15 15.8333H5C4.54 15.8333 4.16667 15.4592 4.16667 15V7.5H15.8333V15C15.8333 15.4592 15.46 15.8333 15 15.8333ZM6.7675 4.41083C6.92333 4.25583 7.1375 4.16667 7.35667 4.16667H12.6433C12.8625 4.16667 13.0767 4.25583 13.2325 4.41083L14.655 5.83333H5.345L6.7675 4.41083ZM16.7675 5.58917L14.4108 3.2325C13.9392 2.76 13.3108 2.5 12.6433 2.5H7.35667C6.68917 2.5 6.06083 2.76 5.58917 3.2325L3.2325 5.58917C2.76 6.06083 2.5 6.68917 2.5 7.3575V15C2.5 16.3783 3.62167 17.5 5 17.5H15C16.3783 17.5 17.5 16.3783 17.5 15V7.3575C17.5 6.68917 17.24 6.06083 16.7675 5.58917Z" />
</mask>
<g mask="url(#ecommerce)">
<rect width="20" height="20"/>
</g>
</svg>
);
export default UserIcon;

View File

@ -0,0 +1,15 @@
import React from 'react';
const EmailIcon = (props) => (
<svg className={props.className} width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fillRule="evenodd" clipRule="evenodd" d="M15.8334 15H4.16669C3.70752 15 3.33335 14.6266 3.33335 14.1666V6.04165L9.50002 10.6666C9.64835 10.7783 9.82419 10.8333 10 10.8333C10.1759 10.8333 10.3517 10.7783 10.5 10.6666L16.6667 6.04165V14.1666C16.6667 14.6266 16.2925 15 15.8334 15ZM15.2775 4.99998L10 8.95831L4.72252 4.99998H15.2775ZM15.8334 3.33331H4.16669C2.78835 3.33331 1.66669 4.45498 1.66669 5.83331V14.1666C1.66669 15.545 2.78835 16.6666 4.16669 16.6666H15.8334C17.2117 16.6666 18.3334 15.545 18.3334 14.1666V5.83331C18.3334 4.45498 17.2117 3.33331 15.8334 3.33331Z" />
<mask id="email" mask-type="alpha" maskUnits="userSpaceOnUse" x="1" y="3" width="18" height="14">
<path fillRule="evenodd" clipRule="evenodd" d="M15.8334 15H4.16669C3.70752 15 3.33335 14.6266 3.33335 14.1666V6.04165L9.50002 10.6666C9.64835 10.7783 9.82419 10.8333 10 10.8333C10.1759 10.8333 10.3517 10.7783 10.5 10.6666L16.6667 6.04165V14.1666C16.6667 14.6266 16.2925 15 15.8334 15ZM15.2775 4.99998L10 8.95831L4.72252 4.99998H15.2775ZM15.8334 3.33331H4.16669C2.78835 3.33331 1.66669 4.45498 1.66669 5.83331V14.1666C1.66669 15.545 2.78835 16.6666 4.16669 16.6666H15.8334C17.2117 16.6666 18.3334 15.545 18.3334 14.1666V5.83331C18.3334 4.45498 17.2117 3.33331 15.8334 3.33331Z" />
</mask>
<g mask="url(#email)">
<rect width="20" height="20" />
</g>
</svg>
);
export default EmailIcon;

View File

@ -0,0 +1,15 @@
import React from 'react';
const ExtraIcon = (props) => (
<svg className={props.className} idth="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
<path fillRule="evenodd" clipRule="evenodd" d="M6.24594 7.93044C4.55261 9.76294 4.58844 12.6679 6.35344 14.4671C7.21511 15.3479 8.36011 15.8338 9.58011 15.8346H9.58428C10.8068 15.8346 11.9559 15.3488 12.8218 14.4671C14.6184 12.6354 14.6151 9.65627 12.8143 7.82711L10.3259 5.28461C10.0743 7.35294 9.29844 9.16794 7.91678 9.16794C7.49344 9.16794 6.80344 8.97961 6.24594 7.93044ZM9.58428 17.5013H9.57845C7.90678 17.4996 6.33845 16.8371 5.16261 15.6329C2.73428 13.1579 2.73095 9.13043 5.15511 6.6596L5.97428 5.83127C6.18595 5.6196 6.49345 5.53793 6.78428 5.61377C7.07345 5.6921 7.29845 5.9196 7.37345 6.2096C7.56511 6.95043 7.79345 7.3146 7.91928 7.45293C8.21511 7.14127 8.75011 5.8821 8.75011 3.75127C8.75011 3.62877 8.75011 3.51293 8.74345 3.3971C8.72761 3.15127 8.82178 2.91043 9.00011 2.74043C9.33095 2.42627 9.86095 2.42627 10.1784 2.75293L14.0034 6.66043C16.4368 9.13043 16.4409 13.1579 14.0118 15.6338C12.8293 16.8388 11.2576 17.5013 9.58428 17.5013Z" />
<mask id="extra" mask-type="alpha" maskUnits="userSpaceOnUse" x="3" y="2" width="13" height="16">
<path fillRule="evenodd" clipRule="evenodd" d="M6.24594 7.93044C4.55261 9.76294 4.58844 12.6679 6.35344 14.4671C7.21511 15.3479 8.36011 15.8338 9.58011 15.8346H9.58428C10.8068 15.8346 11.9559 15.3488 12.8218 14.4671C14.6184 12.6354 14.6151 9.65627 12.8143 7.82711L10.3259 5.28461C10.0743 7.35294 9.29844 9.16794 7.91678 9.16794C7.49344 9.16794 6.80344 8.97961 6.24594 7.93044ZM9.58428 17.5013H9.57845C7.90678 17.4996 6.33845 16.8371 5.16261 15.6329C2.73428 13.1579 2.73095 9.13043 5.15511 6.6596L5.97428 5.83127C6.18595 5.6196 6.49345 5.53793 6.78428 5.61377C7.07345 5.6921 7.29845 5.9196 7.37345 6.2096C7.56511 6.95043 7.79345 7.3146 7.91928 7.45293C8.21511 7.14127 8.75011 5.8821 8.75011 3.75127C8.75011 3.62877 8.75011 3.51293 8.74345 3.3971C8.72761 3.15127 8.82178 2.91043 9.00011 2.74043C9.33095 2.42627 9.86095 2.42627 10.1784 2.75293L14.0034 6.66043C16.4368 9.13043 16.4409 13.1579 14.0118 15.6338C12.8293 16.8388 11.2576 17.5013 9.58428 17.5013Z" />
</mask>
<g mask="url(#extra)">
<rect width="20" height="20" />
</g>
</svg>
);
export default ExtraIcon;

View File

@ -0,0 +1,17 @@
import React from 'react';
const FormsIcon = (props) => (
<svg className={props.className} width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
<path fillRule="evenodd" clipRule="evenodd" d="M7.5 10.8333V10C7.5 8.62167 8.62167 7.5 10 7.5H10.8333V4.7225C10.8333 4.41583 10.5842 4.16667 10.2775 4.16667H4.7225C4.41583 4.16667 4.16667 4.41583 4.16667 4.7225V10.2775C4.16667 10.5842 4.41583 10.8333 4.7225 10.8333H7.5ZM7.5 12.5H4.7225C3.49667 12.5 2.5 11.5033 2.5 10.2775V4.7225C2.5 3.49667 3.49667 2.5 4.7225 2.5H10.2775C11.5033 2.5 12.5 3.49667 12.5 4.7225V7.5H15C16.3783 7.5 17.5 8.62167 17.5 10V15C17.5 16.3783 16.3783 17.5 15 17.5H10C8.62167 17.5 7.5 16.3783 7.5 15V12.5ZM9.16667 10C9.16667 9.54083 9.54083 9.16667 10 9.16667H15C15.46 9.16667 15.8333 9.54083 15.8333 10V15C15.8333 15.4592 15.46 15.8333 15 15.8333H10C9.54083 15.8333 9.16667 15.4592 9.16667 15V10Z" />
<mask id="forms" mask-type="alpha" maskUnits="userSpaceOnUse" x="2" y="2" width="16" height="16">
<path fillRule="evenodd" clipRule="evenodd" d="M7.5 10.8333V10C7.5 8.62167 8.62167 7.5 10 7.5H10.8333V4.7225C10.8333 4.41583 10.5842 4.16667 10.2775 4.16667H4.7225C4.41583 4.16667 4.16667 4.41583 4.16667 4.7225V10.2775C4.16667 10.5842 4.41583 10.8333 4.7225 10.8333H7.5ZM7.5 12.5H4.7225C3.49667 12.5 2.5 11.5033 2.5 10.2775V4.7225C2.5 3.49667 3.49667 2.5 4.7225 2.5H10.2775C11.5033 2.5 12.5 3.49667 12.5 4.7225V7.5H15C16.3783 7.5 17.5 8.62167 17.5 10V15C17.5 16.3783 16.3783 17.5 15 17.5H10C8.62167 17.5 7.5 16.3783 7.5 15V12.5ZM9.16667 10C9.16667 9.54083 9.54083 9.16667 10 9.16667H15C15.46 9.16667 15.8333 9.54083 15.8333 10V15C15.8333 15.4592 15.46 15.8333 15 15.8333H10C9.54083 15.8333 9.16667 15.4592 9.16667 15V10Z" />
</mask>
<g mask="url(#forms)">
<rect width="20" height="20" />
</g>
</svg>
);
export default FormsIcon;

View File

@ -0,0 +1,15 @@
import React from 'react';
const GridIcon = (props) => (
<svg className={props.className} width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
<path fillRule="evenodd" clipRule="evenodd" d="M12.5 15.8333V12.5H15.8333L15.8342 15.8333H12.5ZM15.8333 10.8333H12.5C11.5808 10.8333 10.8333 11.5808 10.8333 12.5V15.8333C10.8333 16.7525 11.5808 17.5 12.5 17.5H15.8333C16.7525 17.5 17.5 16.7525 17.5 15.8333V12.5C17.5 11.5808 16.7525 10.8333 15.8333 10.8333ZM4.16667 15.8333V12.5H7.5L7.50083 15.8333H4.16667ZM7.5 10.8333H4.16667C3.2475 10.8333 2.5 11.5808 2.5 12.5V15.8333C2.5 16.7525 3.2475 17.5 4.16667 17.5H7.5C8.41917 17.5 9.16667 16.7525 9.16667 15.8333V12.5C9.16667 11.5808 8.41917 10.8333 7.5 10.8333ZM12.5 7.5V4.16667H15.8333L15.8342 7.5H12.5ZM15.8333 2.5H12.5C11.5808 2.5 10.8333 3.2475 10.8333 4.16667V7.5C10.8333 8.41917 11.5808 9.16667 12.5 9.16667H15.8333C16.7525 9.16667 17.5 8.41917 17.5 7.5V4.16667C17.5 3.2475 16.7525 2.5 15.8333 2.5ZM4.16667 7.5V4.16667H7.5L7.50083 7.5H4.16667ZM7.5 2.5H4.16667C3.2475 2.5 2.5 3.2475 2.5 4.16667V7.5C2.5 8.41917 3.2475 9.16667 4.16667 9.16667H7.5C8.41917 9.16667 9.16667 8.41917 9.16667 7.5V4.16667C9.16667 3.2475 8.41917 2.5 7.5 2.5Z" />
<mask id="grid" mask-type="alpha" maskUnits="userSpaceOnUse" x="2" y="2" width="16" height="16">
<path fillRule="evenodd" clipRule="evenodd" d="M12.5 15.8333V12.5H15.8333L15.8342 15.8333H12.5ZM15.8333 10.8333H12.5C11.5808 10.8333 10.8333 11.5808 10.8333 12.5V15.8333C10.8333 16.7525 11.5808 17.5 12.5 17.5H15.8333C16.7525 17.5 17.5 16.7525 17.5 15.8333V12.5C17.5 11.5808 16.7525 10.8333 15.8333 10.8333ZM4.16667 15.8333V12.5H7.5L7.50083 15.8333H4.16667ZM7.5 10.8333H4.16667C3.2475 10.8333 2.5 11.5808 2.5 12.5V15.8333C2.5 16.7525 3.2475 17.5 4.16667 17.5H7.5C8.41917 17.5 9.16667 16.7525 9.16667 15.8333V12.5C9.16667 11.5808 8.41917 10.8333 7.5 10.8333ZM12.5 7.5V4.16667H15.8333L15.8342 7.5H12.5ZM15.8333 2.5H12.5C11.5808 2.5 10.8333 3.2475 10.8333 4.16667V7.5C10.8333 8.41917 11.5808 9.16667 12.5 9.16667H15.8333C16.7525 9.16667 17.5 8.41917 17.5 7.5V4.16667C17.5 3.2475 16.7525 2.5 15.8333 2.5ZM4.16667 7.5V4.16667H7.5L7.50083 7.5H4.16667ZM7.5 2.5H4.16667C3.2475 2.5 2.5 3.2475 2.5 4.16667V7.5C2.5 8.41917 3.2475 9.16667 4.16667 9.16667H7.5C8.41917 9.16667 9.16667 8.41917 9.16667 7.5V4.16667C9.16667 3.2475 8.41917 2.5 7.5 2.5Z" />
</mask>
<g mask="url(#grid)">
<rect width="20" height="20"/>
</g>
</svg>
);
export default GridIcon;

View File

@ -0,0 +1,15 @@
import React from 'react';
const LBPackageIcon = (props) => (
<svg className={props.className} width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
<path fillRule="evenodd" clipRule="evenodd" d="M14.8002 12.95L10.0002 15.7059L5.20023 12.95L6.6119 12.3492L9.58523 14.0559C9.71357 14.13 9.8569 14.1667 10.0002 14.1667C10.1436 14.1667 10.2861 14.13 10.4152 14.0559L13.3886 12.3484L14.8002 12.95ZM9.58523 10.7225C9.71357 10.7967 9.8569 10.8334 10.0002 10.8334C10.1436 10.8334 10.2861 10.7967 10.4152 10.7225L13.3886 9.01503L14.8002 9.61669L10.0002 12.3725L5.20023 9.61669L6.6119 9.01503L9.58523 10.7225ZM10.0002 4.23919L14.8002 6.28335L10.0002 9.03919L5.20023 6.28335L10.0002 4.23919ZM17.4986 9.45669C17.4794 9.14086 17.2836 8.86336 16.9927 8.73919L15.1994 7.97586L17.0819 6.89503C17.3561 6.73836 17.5169 6.43919 17.4986 6.12336C17.4794 5.80836 17.2836 5.53003 16.9927 5.40586L10.3261 2.56669C10.1177 2.47753 9.8819 2.47753 9.67357 2.56669L3.0069 5.40586C2.71607 5.53003 2.52023 5.80836 2.5019 6.12336C2.48273 6.43919 2.6444 6.73836 2.91857 6.89503L4.80023 7.97586L3.0069 8.73919C2.71607 8.86336 2.52023 9.14086 2.5019 9.45669C2.48273 9.77253 2.6444 10.0717 2.91857 10.2284L4.80023 11.3092L3.0069 12.0725C2.71607 12.1967 2.52023 12.4742 2.5019 12.79C2.48273 13.1059 2.6444 13.405 2.91857 13.5617L9.58523 17.3892C9.71357 17.4634 9.8569 17.5 10.0002 17.5C10.1436 17.5 10.2861 17.4634 10.4152 17.3892L17.0819 13.5617C17.3561 13.405 17.5169 13.1059 17.4986 12.79C17.4794 12.475 17.2836 12.1967 16.9936 12.0725L15.2002 11.3084L17.0819 10.2284C17.3561 10.0717 17.5169 9.77253 17.4986 9.45669Z" />
<mask id="lbpackage" mask-type="alpha" maskUnits="userSpaceOnUse" x="2" y="2" width="16" height="16">
<path fillRule="evenodd" clipRule="evenodd" d="M14.8002 12.95L10.0002 15.7059L5.20023 12.95L6.6119 12.3492L9.58523 14.0559C9.71357 14.13 9.8569 14.1667 10.0002 14.1667C10.1436 14.1667 10.2861 14.13 10.4152 14.0559L13.3886 12.3484L14.8002 12.95ZM9.58523 10.7225C9.71357 10.7967 9.8569 10.8334 10.0002 10.8334C10.1436 10.8334 10.2861 10.7967 10.4152 10.7225L13.3886 9.01503L14.8002 9.61669L10.0002 12.3725L5.20023 9.61669L6.6119 9.01503L9.58523 10.7225ZM10.0002 4.23919L14.8002 6.28335L10.0002 9.03919L5.20023 6.28335L10.0002 4.23919ZM17.4986 9.45669C17.4794 9.14086 17.2836 8.86336 16.9927 8.73919L15.1994 7.97586L17.0819 6.89503C17.3561 6.73836 17.5169 6.43919 17.4986 6.12336C17.4794 5.80836 17.2836 5.53003 16.9927 5.40586L10.3261 2.56669C10.1177 2.47753 9.8819 2.47753 9.67357 2.56669L3.0069 5.40586C2.71607 5.53003 2.52023 5.80836 2.5019 6.12336C2.48273 6.43919 2.6444 6.73836 2.91857 6.89503L4.80023 7.97586L3.0069 8.73919C2.71607 8.86336 2.52023 9.14086 2.5019 9.45669C2.48273 9.77253 2.6444 10.0717 2.91857 10.2284L4.80023 11.3092L3.0069 12.0725C2.71607 12.1967 2.52023 12.4742 2.5019 12.79C2.48273 13.1059 2.6444 13.405 2.91857 13.5617L9.58523 17.3892C9.71357 17.4634 9.8569 17.5 10.0002 17.5C10.1436 17.5 10.2861 17.4634 10.4152 17.3892L17.0819 13.5617C17.3561 13.405 17.5169 13.1059 17.4986 12.79C17.4794 12.475 17.2836 12.1967 16.9936 12.0725L15.2002 11.3084L17.0819 10.2284C17.3561 10.0717 17.5169 9.77253 17.4986 9.45669Z" />
</mask>
<g mask="url(#lbpackage)">
<rect width="20" height="20" />
</g>
</svg>
);
export default LBPackageIcon;

View File

@ -0,0 +1,15 @@
import React from 'react';
const MapsIcon = (props) => (
<svg className={props.className} idth="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
<path fillRule="evenodd" clipRule="evenodd" d="M9.99998 9.16621C9.31081 9.16621 8.74998 8.60537 8.74998 7.91621C8.74998 7.22704 9.31081 6.66621 9.99998 6.66621C10.6891 6.66621 11.25 7.22704 11.25 7.91621C11.25 8.60537 10.6891 9.16621 9.99998 9.16621ZM9.99998 4.99954C8.39165 4.99954 7.08331 6.30787 7.08331 7.91621C7.08331 9.52454 8.39165 10.8329 9.99998 10.8329C11.6083 10.8329 12.9166 9.52454 12.9166 7.91621C12.9166 6.30787 11.6083 4.99954 9.99998 4.99954ZM9.99998 16.3716C8.60415 15.0516 4.99998 11.3458 4.99998 8.26829C4.99998 5.54746 7.24248 3.33329 9.99998 3.33329C12.7575 3.33329 15 5.54746 15 8.26829C15 11.3458 11.3958 15.0516 9.99998 16.3716ZM9.99998 1.66663C6.32415 1.66663 3.33331 4.62746 3.33331 8.26829C3.33331 12.8308 9.20748 17.9175 9.45748 18.1316C9.61415 18.2658 9.80665 18.3333 9.99998 18.3333C10.1933 18.3333 10.3858 18.2658 10.5425 18.1316C10.7925 17.9175 16.6666 12.8308 16.6666 8.26829C16.6666 4.62746 13.6758 1.66663 9.99998 1.66663Z" />
<mask id="maps" mask-type="alpha" maskUnits="userSpaceOnUse" x="3" y="1" width="14" height="18">
<path fillRule="evenodd" clipRule="evenodd" d="M9.99998 9.16621C9.31081 9.16621 8.74998 8.60537 8.74998 7.91621C8.74998 7.22704 9.31081 6.66621 9.99998 6.66621C10.6891 6.66621 11.25 7.22704 11.25 7.91621C11.25 8.60537 10.6891 9.16621 9.99998 9.16621ZM9.99998 4.99954C8.39165 4.99954 7.08331 6.30787 7.08331 7.91621C7.08331 9.52454 8.39165 10.8329 9.99998 10.8329C11.6083 10.8329 12.9166 9.52454 12.9166 7.91621C12.9166 6.30787 11.6083 4.99954 9.99998 4.99954ZM9.99998 16.3716C8.60415 15.0516 4.99998 11.3458 4.99998 8.26829C4.99998 5.54746 7.24248 3.33329 9.99998 3.33329C12.7575 3.33329 15 5.54746 15 8.26829C15 11.3458 11.3958 15.0516 9.99998 16.3716ZM9.99998 1.66663C6.32415 1.66663 3.33331 4.62746 3.33331 8.26829C3.33331 12.8308 9.20748 17.9175 9.45748 18.1316C9.61415 18.2658 9.80665 18.3333 9.99998 18.3333C10.1933 18.3333 10.3858 18.2658 10.5425 18.1316C10.7925 17.9175 16.6666 12.8308 16.6666 8.26829C16.6666 4.62746 13.6758 1.66663 9.99998 1.66663Z" />
</mask>
<g mask="url(#maps)">
<rect width="20" height="20" />
</g>
</svg>
);
export default MapsIcon;

View File

@ -0,0 +1,15 @@
import React from 'react';
const MenuIcon = (props) => (
<svg className={props.className} width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
<path fillRule="evenodd" clipRule="evenodd" d="M2.5 5.83333C2.5 5.37333 2.87333 5 3.33333 5C3.79333 5 4.16667 5.37333 4.16667 5.83333C4.16667 6.29333 3.79333 6.66667 3.33333 6.66667C2.87333 6.66667 2.5 6.29333 2.5 5.83333ZM2.5 10C2.5 9.54 2.87333 9.16667 3.33333 9.16667C3.79333 9.16667 4.16667 9.54 4.16667 10C4.16667 10.46 3.79333 10.8333 3.33333 10.8333C2.87333 10.8333 2.5 10.46 2.5 10ZM3.33333 13.3333C2.87333 13.3333 2.5 13.7067 2.5 14.1667C2.5 14.6267 2.87333 15 3.33333 15C3.79333 15 4.16667 14.6267 4.16667 14.1667C4.16667 13.7067 3.79333 13.3333 3.33333 13.3333ZM6.61292 9.16667H16.7204C17.1496 9.16667 17.5004 9.5175 17.5004 9.94667V10.0533C17.5004 10.4825 17.1496 10.8333 16.7204 10.8333H6.61292C6.18375 10.8333 5.83375 10.4825 5.83375 10.0533V9.94667C5.83375 9.5175 6.18375 9.16667 6.61292 9.16667ZM16.7204 13.3333H6.61292C6.18375 13.3333 5.83375 13.6842 5.83375 14.1133V14.22C5.83375 14.6492 6.18375 15 6.61292 15H16.7204C17.1496 15 17.5004 14.6492 17.5004 14.22V14.1133C17.5004 13.6842 17.1496 13.3333 16.7204 13.3333ZM6.61292 5H16.7204C17.1496 5 17.5004 5.35083 17.5004 5.78V5.88667C17.5004 6.31583 17.1496 6.66667 16.7204 6.66667H6.61292C6.18375 6.66667 5.83375 6.31583 5.83375 5.88667V5.78C5.83375 5.35083 6.18375 5 6.61292 5Z" />
<mask id="menu" mask-type="alpha" maskUnits="userSpaceOnUse" x="2" y="5" width="16" height="10">
<path fillRule="evenodd" clipRule="evenodd" d="M2.5 5.83333C2.5 5.37333 2.87333 5 3.33333 5C3.79333 5 4.16667 5.37333 4.16667 5.83333C4.16667 6.29333 3.79333 6.66667 3.33333 6.66667C2.87333 6.66667 2.5 6.29333 2.5 5.83333ZM2.5 10C2.5 9.54 2.87333 9.16667 3.33333 9.16667C3.79333 9.16667 4.16667 9.54 4.16667 10C4.16667 10.46 3.79333 10.8333 3.33333 10.8333C2.87333 10.8333 2.5 10.46 2.5 10ZM3.33333 13.3333C2.87333 13.3333 2.5 13.7067 2.5 14.1667C2.5 14.6267 2.87333 15 3.33333 15C3.79333 15 4.16667 14.6267 4.16667 14.1667C4.16667 13.7067 3.79333 13.3333 3.33333 13.3333ZM6.61292 9.16667H16.7204C17.1496 9.16667 17.5004 9.5175 17.5004 9.94667V10.0533C17.5004 10.4825 17.1496 10.8333 16.7204 10.8333H6.61292C6.18375 10.8333 5.83375 10.4825 5.83375 10.0533V9.94667C5.83375 9.5175 6.18375 9.16667 6.61292 9.16667ZM16.7204 13.3333H6.61292C6.18375 13.3333 5.83375 13.6842 5.83375 14.1133V14.22C5.83375 14.6492 6.18375 15 6.61292 15H16.7204C17.1496 15 17.5004 14.6492 17.5004 14.22V14.1133C17.5004 13.6842 17.1496 13.3333 16.7204 13.3333ZM6.61292 5H16.7204C17.1496 5 17.5004 5.35083 17.5004 5.78V5.88667C17.5004 6.31583 17.1496 6.66667 16.7204 6.66667H6.61292C6.18375 6.66667 5.83375 6.31583 5.83375 5.88667V5.78C5.83375 5.35083 6.18375 5 6.61292 5Z" />
</mask>
<g mask="url(#menu)">
<rect width="20" height="20" />
</g>
</svg>
);
export default MenuIcon;

View File

@ -0,0 +1,15 @@
import React from 'react';
const TablesIcon = (props) => (
<svg className={props.className} width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
<path fillRule="evenodd" clipRule="evenodd" d="M15 15.8333H10.8333V8.33333H15.8333V15C15.8333 15.46 15.4592 15.8333 15 15.8333ZM4.16667 15V8.33333H9.16667V15.8333H5C4.54083 15.8333 4.16667 15.46 4.16667 15ZM5 4.16667H15C15.4592 4.16667 15.8333 4.54 15.8333 5V6.66667H4.16667V5C4.16667 4.54 4.54083 4.16667 5 4.16667ZM15 2.5H5C3.62167 2.5 2.5 3.62167 2.5 5V7.34833V7.65167V15C2.5 16.3783 3.62167 17.5 5 17.5H15C16.3783 17.5 17.5 16.3783 17.5 15V7.65167V7.34833V5C17.5 3.62167 16.3783 2.5 15 2.5Z" />
<mask id="tables" mask-type="alpha" maskUnits="userSpaceOnUse" x="2" y="2" width="16" height="16">
<path fillRule="evenodd" clipRule="evenodd" d="M15 15.8333H10.8333V8.33333H15.8333V15C15.8333 15.46 15.4592 15.8333 15 15.8333ZM4.16667 15V8.33333H9.16667V15.8333H5C4.54083 15.8333 4.16667 15.46 4.16667 15ZM5 4.16667H15C15.4592 4.16667 15.8333 4.54 15.8333 5V6.66667H4.16667V5C4.16667 4.54 4.54083 4.16667 5 4.16667ZM15 2.5H5C3.62167 2.5 2.5 3.62167 2.5 5V7.34833V7.65167V15C2.5 16.3783 3.62167 17.5 5 17.5H15C16.3783 17.5 17.5 16.3783 17.5 15V7.65167V7.34833V5C17.5 3.62167 16.3783 2.5 15 2.5Z" />
</mask>
<g mask="url(#tables)">
<rect width="20" height="20" />
</g>
</svg>
);
export default TablesIcon;

View File

@ -0,0 +1,17 @@
import React from 'react';
const UIElementsIcon = (props) => (
<svg className={props.className} width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
<path fillRule="evenodd" clipRule="evenodd" d="M5.83333 5.83333C5.83333 5.3725 6.20667 5 6.66667 5C7.12667 5 7.5 5.3725 7.5 5.83333C7.5 6.29417 7.12667 6.66667 6.66667 6.66667C6.20667 6.66667 5.83333 6.29417 5.83333 5.83333ZM9.16667 5.83333C9.16667 5.3725 9.54 5 10 5C10.46 5 10.8333 5.3725 10.8333 5.83333C10.8333 6.29417 10.46 6.66667 10 6.66667C9.54 6.66667 9.16667 6.29417 9.16667 5.83333ZM4.16667 7.5V5C4.16667 4.54 4.54083 4.16667 5 4.16667H15C15.4592 4.16667 15.8333 4.54 15.8333 5V7.5H4.16667ZM15.8333 15C15.8333 15.46 15.4592 15.8333 15 15.8333H5C4.54083 15.8333 4.16667 15.46 4.16667 15V9.16667H15.8333V15ZM15 2.5H5C3.62167 2.5 2.5 3.62167 2.5 5V7.5V9.16667V15C2.5 16.3783 3.62167 17.5 5 17.5H15C16.3783 17.5 17.5 16.3783 17.5 15V9.16667V7.5V5C17.5 3.62167 16.3783 2.5 15 2.5Z"/>
<mask id="uielements" mask-type="alpha" maskUnits="userSpaceOnUse" x="2" y="2" width="16" height="16">
<path fillRule="evenodd" clipule="evenodd" d="M5.83333 5.83333C5.83333 5.3725 6.20667 5 6.66667 5C7.12667 5 7.5 5.3725 7.5 5.83333C7.5 6.29417 7.12667 6.66667 6.66667 6.66667C6.20667 6.66667 5.83333 6.29417 5.83333 5.83333ZM9.16667 5.83333C9.16667 5.3725 9.54 5 10 5C10.46 5 10.8333 5.3725 10.8333 5.83333C10.8333 6.29417 10.46 6.66667 10 6.66667C9.54 6.66667 9.16667 6.29417 9.16667 5.83333ZM4.16667 7.5V5C4.16667 4.54 4.54083 4.16667 5 4.16667H15C15.4592 4.16667 15.8333 4.54 15.8333 5V7.5H4.16667ZM15.8333 15C15.8333 15.46 15.4592 15.8333 15 15.8333H5C4.54083 15.8333 4.16667 15.46 4.16667 15V9.16667H15.8333V15ZM15 2.5H5C3.62167 2.5 2.5 3.62167 2.5 5V7.5V9.16667V15C2.5 16.3783 3.62167 17.5 5 17.5H15C16.3783 17.5 17.5 16.3783 17.5 15V9.16667V7.5V5C17.5 3.62167 16.3783 2.5 15 2.5Z"/>
</mask>
<g mask="url(#uielements)">
<rect width="20" height="20"/>
</g>
</svg>
);
export default UIElementsIcon;

View File

@ -0,0 +1,15 @@
import React from 'react';
const UserIcon = (props) => (
<svg className={props.className} width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fillRule="evenodd" clipRule="evenodd" d="M11.6667 5.83333C11.6667 4.91417 10.9192 4.16667 10 4.16667C9.08085 4.16667 8.33335 4.91417 8.33335 5.83333C8.33335 6.7525 9.08085 7.5 10 7.5C10.9192 7.5 11.6667 6.7525 11.6667 5.83333ZM13.3334 5.83333C13.3334 7.67167 11.8384 9.16667 10 9.16667C8.16169 9.16667 6.66669 7.67167 6.66669 5.83333C6.66669 3.995 8.16169 2.5 10 2.5C11.8384 2.5 13.3334 3.995 13.3334 5.83333ZM4.16669 16.6667C4.16669 13.45 6.78419 10.8333 10 10.8333C13.2159 10.8333 15.8334 13.45 15.8334 16.6667C15.8334 17.1267 15.4609 17.5 15 17.5C14.5392 17.5 14.1667 17.1267 14.1667 16.6667C14.1667 14.3692 12.2975 12.5 10 12.5C7.70252 12.5 5.83335 14.3692 5.83335 16.6667C5.83335 17.1267 5.46085 17.5 5.00002 17.5C4.53919 17.5 4.16669 17.1267 4.16669 16.6667Z" />
<mask id="user" mask-type="alpha" maskUnits="userSpaceOnUse" x="4" y="2" width="12" height="16">
<path fillRule="evenodd" clipRule="evenodd" d="M11.6667 5.83333C11.6667 4.91417 10.9192 4.16667 10 4.16667C9.08085 4.16667 8.33335 4.91417 8.33335 5.83333C8.33335 6.7525 9.08085 7.5 10 7.5C10.9192 7.5 11.6667 6.7525 11.6667 5.83333ZM13.3334 5.83333C13.3334 7.67167 11.8384 9.16667 10 9.16667C8.16169 9.16667 6.66669 7.67167 6.66669 5.83333C6.66669 3.995 8.16169 2.5 10 2.5C11.8384 2.5 13.3334 3.995 13.3334 5.83333ZM4.16669 16.6667C4.16669 13.45 6.78419 10.8333 10 10.8333C13.2159 10.8333 15.8334 13.45 15.8334 16.6667C15.8334 17.1267 15.4609 17.5 15 17.5C14.5392 17.5 14.1667 17.1267 14.1667 16.6667C14.1667 14.3692 12.2975 12.5 10 12.5C7.70252 12.5 5.83335 14.3692 5.83335 16.6667C5.83335 17.1267 5.46085 17.5 5.00002 17.5C4.53919 17.5 4.16669 17.1267 4.16669 16.6667Z" />
</mask>
<g mask="url(#user)">
<rect width="20" height="20" />
</g>
</svg>
);
export default UserIcon;

View File

@ -0,0 +1,19 @@
import React from 'react'
const Apps = () => (
<svg width="24" height="24" viewBox="0 0 24 24" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
<path fillRule="evenodd" clipRule="evenodd" d="M6.06668 3.87389C5.364 3.79535 4.636 3.79535 3.93332 3.87389C3.92027 3.87535 3.90735 3.88125 3.89674 3.89172C3.88638 3.90193 3.88233 3.91226 3.88131 3.92103C3.79746 4.6379 3.79746 5.3621 3.88131 6.07897C3.88233 6.08774 3.88638 6.09807 3.89674 6.10829C3.90735 6.11875 3.92027 6.12466 3.93332 6.12611C4.636 6.20465 5.364 6.20465 6.06668 6.12611C6.07973 6.12466 6.09264 6.11875 6.10326 6.10829C6.11362 6.09807 6.11767 6.08774 6.11869 6.07897C6.20254 5.3621 6.20254 4.6379 6.11869 3.92103C6.11767 3.91226 6.11362 3.90193 6.10326 3.89172C6.09264 3.88125 6.07973 3.87535 6.06668 3.87389ZM3.76671 2.38317C4.58012 2.29226 5.41988 2.29226 6.23329 2.38317C6.94562 2.46278 7.52391 3.02322 7.60854 3.74678C7.70592 4.57942 7.70592 5.42058 7.60854 6.25323C7.52391 6.97678 6.94562 7.53722 6.23329 7.61683C5.41988 7.70774 4.58012 7.70774 3.76671 7.61683C3.05438 7.53722 2.47609 6.97679 2.39146 6.25323C2.29408 5.42058 2.29408 4.57942 2.39146 3.74678C2.47609 3.02322 3.05438 2.46278 3.76671 2.38317Z" />
<path fillRule="evenodd" clipRule="evenodd" d="M13.0667 3.87389C12.364 3.79535 11.636 3.79535 10.9333 3.87389C10.9203 3.87535 10.9074 3.88125 10.8967 3.89172C10.8864 3.90193 10.8823 3.91226 10.8813 3.92103C10.7975 4.6379 10.7975 5.3621 10.8813 6.07897C10.8823 6.08774 10.8864 6.09807 10.8967 6.10829C10.9074 6.11875 10.9203 6.12466 10.9333 6.12611C11.636 6.20465 12.364 6.20465 13.0667 6.12611C13.0797 6.12466 13.0926 6.11875 13.1033 6.10829C13.1136 6.09807 13.1177 6.08774 13.1187 6.07897C13.2025 5.3621 13.2025 4.6379 13.1187 3.92103C13.1177 3.91226 13.1136 3.90193 13.1033 3.89172C13.0926 3.88125 13.0797 3.87535 13.0667 3.87389ZM10.7667 2.38317C11.5801 2.29226 12.4199 2.29226 13.2333 2.38317C13.9456 2.46278 14.5239 3.02322 14.6085 3.74678C14.7059 4.57942 14.7059 5.42058 14.6085 6.25323C14.5239 6.97678 13.9456 7.53722 13.2333 7.61683C12.4199 7.70774 11.5801 7.70774 10.7667 7.61683C10.0544 7.53722 9.47609 6.97679 9.39146 6.25323C9.29408 5.42058 9.29408 4.57942 9.39146 3.74678C9.47609 3.02322 10.0544 2.46278 10.7667 2.38317Z" />
<path fillRule="evenodd" clipRule="evenodd" d="M20.0667 3.87389C19.364 3.79535 18.636 3.79535 17.9333 3.87389C17.9203 3.87535 17.9074 3.88125 17.8967 3.89172C17.8864 3.90193 17.8823 3.91226 17.8813 3.92103C17.7975 4.6379 17.7975 5.3621 17.8813 6.07897C17.8823 6.08774 17.8864 6.09807 17.8967 6.10829C17.9074 6.11875 17.9203 6.12466 17.9333 6.12611C18.636 6.20465 19.364 6.20465 20.0667 6.12611C20.0797 6.12466 20.0926 6.11875 20.1033 6.10829C20.1136 6.09807 20.1177 6.08774 20.1187 6.07897C20.2025 5.3621 20.2025 4.6379 20.1187 3.92103C20.1177 3.91226 20.1136 3.90193 20.1033 3.89172C20.0926 3.88125 20.0797 3.87535 20.0667 3.87389ZM17.7667 2.38317C18.5801 2.29226 19.4199 2.29226 20.2333 2.38317C20.9456 2.46278 21.5239 3.02322 21.6085 3.74678C21.7059 4.57942 21.7059 5.42058 21.6085 6.25323C21.5239 6.97678 20.9456 7.53722 20.2333 7.61683C19.4199 7.70774 18.5801 7.70774 17.7667 7.61683C17.0544 7.53722 16.4761 6.97679 16.3915 6.25323C16.2941 5.42058 16.2941 4.57942 16.3915 3.74678C16.4761 3.02322 17.0544 2.46278 17.7667 2.38317Z" />
<path fillRule="evenodd" clipRule="evenodd" d="M6.06668 10.8739C5.364 10.7954 4.636 10.7954 3.93332 10.8739C3.92027 10.8753 3.90735 10.8813 3.89674 10.8917C3.88638 10.9019 3.88233 10.9123 3.88131 10.921C3.79746 11.6379 3.79746 12.3621 3.88131 13.079C3.88233 13.0877 3.88638 13.0981 3.89674 13.1083C3.90735 13.1187 3.92027 13.1247 3.93332 13.1261C4.636 13.2046 5.364 13.2046 6.06668 13.1261C6.07973 13.1247 6.09264 13.1187 6.10326 13.1083C6.11362 13.0981 6.11767 13.0877 6.11869 13.079C6.20254 12.3621 6.20254 11.6379 6.11869 10.921C6.11767 10.9123 6.11362 10.9019 6.10326 10.8917C6.09264 10.8813 6.07973 10.8753 6.06668 10.8739ZM3.76671 9.38317C4.58012 9.29226 5.41988 9.29226 6.23329 9.38317C6.94562 9.46278 7.52391 10.0232 7.60854 10.7468C7.70592 11.5794 7.70592 12.4206 7.60854 13.2532C7.52391 13.9768 6.94562 14.5372 6.23329 14.6168C5.41988 14.7077 4.58012 14.7077 3.76671 14.6168C3.05438 14.5372 2.47609 13.9768 2.39146 13.2532C2.29408 12.4206 2.29408 11.5794 2.39146 10.7468C2.47609 10.0232 3.05438 9.46278 3.76671 9.38317Z" />
<path fillRule="evenodd" clipRule="evenodd" d="M13.0667 10.8739C12.364 10.7954 11.636 10.7954 10.9333 10.8739C10.9203 10.8753 10.9074 10.8813 10.8967 10.8917C10.8864 10.9019 10.8823 10.9123 10.8813 10.921C10.7975 11.6379 10.7975 12.3621 10.8813 13.079C10.8823 13.0877 10.8864 13.0981 10.8967 13.1083C10.9074 13.1187 10.9203 13.1247 10.9333 13.1261C11.636 13.2046 12.364 13.2046 13.0667 13.1261C13.0797 13.1247 13.0926 13.1187 13.1033 13.1083C13.1136 13.0981 13.1177 13.0877 13.1187 13.079C13.2025 12.3621 13.2025 11.6379 13.1187 10.921C13.1177 10.9123 13.1136 10.9019 13.1033 10.8917C13.0926 10.8813 13.0797 10.8753 13.0667 10.8739ZM10.7667 9.38317C11.5801 9.29226 12.4199 9.29226 13.2333 9.38317C13.9456 9.46278 14.5239 10.0232 14.6085 10.7468C14.7059 11.5794 14.7059 12.4206 14.6085 13.2532C14.5239 13.9768 13.9456 14.5372 13.2333 14.6168C12.4199 14.7077 11.5801 14.7077 10.7667 14.6168C10.0544 14.5372 9.47609 13.9768 9.39146 13.2532C9.29408 12.4206 9.29408 11.5794 9.39146 10.7468C9.47609 10.0232 10.0544 9.46278 10.7667 9.38317Z" />
<path fillRule="evenodd" clipRule="evenodd" d="M20.0667 10.8739C19.364 10.7954 18.636 10.7954 17.9333 10.8739C17.9203 10.8753 17.9074 10.8813 17.8967 10.8917C17.8864 10.9019 17.8823 10.9123 17.8813 10.921C17.7975 11.6379 17.7975 12.3621 17.8813 13.079C17.8823 13.0877 17.8864 13.0981 17.8967 13.1083C17.9074 13.1187 17.9203 13.1247 17.9333 13.1261C18.636 13.2046 19.364 13.2046 20.0667 13.1261C20.0797 13.1247 20.0926 13.1187 20.1033 13.1083C20.1136 13.0981 20.1177 13.0877 20.1187 13.079C20.2025 12.3621 20.2025 11.6379 20.1187 10.921C20.1177 10.9123 20.1136 10.9019 20.1033 10.8917C20.0926 10.8813 20.0797 10.8753 20.0667 10.8739ZM17.7667 9.38317C18.5801 9.29226 19.4199 9.29226 20.2333 9.38317C20.9456 9.46278 21.5239 10.0232 21.6085 10.7468C21.7059 11.5794 21.7059 12.4206 21.6085 13.2532C21.5239 13.9768 20.9456 14.5372 20.2333 14.6168C19.4199 14.7077 18.5801 14.7077 17.7667 14.6168C17.0544 14.5372 16.4761 13.9768 16.3915 13.2532C16.2941 12.4206 16.2941 11.5794 16.3915 10.7468C16.4761 10.0232 17.0544 9.46278 17.7667 9.38317Z" />
<path fillRule="evenodd" clipRule="evenodd" d="M6.06668 17.8739C5.364 17.7954 4.636 17.7954 3.93332 17.8739C3.92027 17.8753 3.90735 17.8813 3.89674 17.8917C3.88638 17.9019 3.88233 17.9123 3.88131 17.921C3.79746 18.6379 3.79746 19.3621 3.88131 20.079C3.88233 20.0877 3.88638 20.0981 3.89674 20.1083C3.90735 20.1187 3.92027 20.1247 3.93332 20.1261C4.636 20.2046 5.364 20.2046 6.06668 20.1261C6.07973 20.1247 6.09264 20.1187 6.10326 20.1083C6.11362 20.0981 6.11767 20.0877 6.11869 20.079C6.20254 19.3621 6.20254 18.6379 6.11869 17.921C6.11767 17.9123 6.11362 17.9019 6.10326 17.8917C6.09264 17.8813 6.07973 17.8753 6.06668 17.8739ZM3.76671 16.3832C4.58012 16.2923 5.41988 16.2923 6.23329 16.3832C6.94562 16.4628 7.52391 17.0232 7.60854 17.7468C7.70592 18.5794 7.70592 19.4206 7.60854 20.2532C7.52391 20.9768 6.94562 21.5372 6.23329 21.6168C5.41988 21.7077 4.58012 21.7077 3.76671 21.6168C3.05438 21.5372 2.47609 20.9768 2.39146 20.2532C2.29408 19.4206 2.29408 18.5794 2.39146 17.7468C2.47609 17.0232 3.05438 16.4628 3.76671 16.3832Z" />
<path fillRule="evenodd" clipRule="evenodd" d="M13.0667 17.8739C12.364 17.7954 11.636 17.7954 10.9333 17.8739C10.9203 17.8753 10.9074 17.8813 10.8967 17.8917C10.8864 17.9019 10.8823 17.9123 10.8813 17.921C10.7975 18.6379 10.7975 19.3621 10.8813 20.079C10.8823 20.0877 10.8864 20.0981 10.8967 20.1083C10.9074 20.1187 10.9203 20.1247 10.9333 20.1261C11.636 20.2046 12.364 20.2046 13.0667 20.1261C13.0797 20.1247 13.0926 20.1187 13.1033 20.1083C13.1136 20.0981 13.1177 20.0877 13.1187 20.079C13.2025 19.3621 13.2025 18.6379 13.1187 17.921C13.1177 17.9123 13.1136 17.9019 13.1033 17.8917C13.0926 17.8813 13.0797 17.8753 13.0667 17.8739ZM10.7667 16.3832C11.5801 16.2923 12.4199 16.2923 13.2333 16.3832C13.9456 16.4628 14.5239 17.0232 14.6085 17.7468C14.7059 18.5794 14.7059 19.4206 14.6085 20.2532C14.5239 20.9768 13.9456 21.5372 13.2333 21.6168C12.4199 21.7077 11.5801 21.7077 10.7667 21.6168C10.0544 21.5372 9.47609 20.9768 9.39146 20.2532C9.29408 19.4206 9.29408 18.5794 9.39146 17.7468C9.47609 17.0232 10.0544 16.4628 10.7667 16.3832Z" />
<path fillRule="evenodd" clipRule="evenodd" d="M20.0667 17.8739C19.364 17.7954 18.636 17.7954 17.9333 17.8739C17.9203 17.8753 17.9074 17.8813 17.8967 17.8917C17.8864 17.9019 17.8823 17.9123 17.8813 17.921C17.7975 18.6379 17.7975 19.3621 17.8813 20.079C17.8823 20.0877 17.8864 20.0981 17.8967 20.1083C17.9074 20.1187 17.9203 20.1247 17.9333 20.1261C18.636 20.2046 19.364 20.2046 20.0667 20.1261C20.0797 20.1247 20.0926 20.1187 20.1033 20.1083C20.1136 20.0981 20.1177 20.0877 20.1187 20.079C20.2025 19.3621 20.2025 18.6379 20.1187 17.921C20.1177 17.9123 20.1136 17.9019 20.1033 17.8917C20.0926 17.8813 20.0797 17.8753 20.0667 17.8739ZM17.7667 16.3832C18.5801 16.2923 19.4199 16.2923 20.2333 16.3832C20.9456 16.4628 21.5239 17.0232 21.6085 17.7468C21.7059 18.5794 21.7059 19.4206 21.6085 20.2532C21.5239 20.9768 20.9456 21.5372 20.2333 21.6168C19.4199 21.7077 18.5801 21.7077 17.7667 21.6168C17.0544 21.5372 16.4761 20.9768 16.3915 20.2532C16.2941 19.4206 16.2941 18.5794 16.3915 17.7468C16.4761 17.0232 17.0544 16.4628 17.7667 16.3832Z" />
</svg>
)
export default Apps

View File

@ -0,0 +1,14 @@
import React from 'react'
const Asana = () => (
<svg width="24" height="24" viewBox="0 0 24 24" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
<path fillRule="evenodd" clipRule="evenodd" d="M10.4693 3.55448C10.9546 3.35346 11.4747 3.25 12 3.25C12.5253 3.25 13.0454 3.35346 13.5307 3.55448C14.016 3.7555 14.457 4.05014 14.8284 4.42157C15.1999 4.79301 15.4945 5.23397 15.6955 5.71927C15.8965 6.20457 16 6.72471 16 7.25C16 7.77529 15.8965 8.29543 15.6955 8.78073C15.4945 9.26603 15.1999 9.70699 14.8284 10.0784C14.457 10.4499 14.016 10.7445 13.5307 10.9455C13.0454 11.1465 12.5253 11.25 12 11.25C11.4747 11.25 10.9546 11.1465 10.4693 10.9455C9.98396 10.7445 9.54301 10.4499 9.17157 10.0784C8.80014 9.70699 8.5055 9.26604 8.30448 8.78073C8.10346 8.29543 8 7.77529 8 7.25C8 6.72471 8.10346 6.20457 8.30448 5.71927C8.5055 5.23396 8.80014 4.79301 9.17157 4.42157C9.54301 4.05014 9.98396 3.7555 10.4693 3.55448ZM12 4.75C11.6717 4.75 11.3466 4.81466 11.0433 4.9403C10.74 5.06594 10.4644 5.25009 10.2322 5.48223C10.0001 5.71438 9.81594 5.98998 9.6903 6.29329C9.56466 6.59661 9.5 6.92169 9.5 7.25C9.5 7.5783 9.56466 7.90339 9.6903 8.20671C9.81594 8.51002 10.0001 8.78562 10.2322 9.01777C10.4644 9.24991 10.74 9.43406 11.0433 9.5597C11.3466 9.68534 11.6717 9.75 12 9.75C12.3283 9.75 12.6534 9.68534 12.9567 9.5597C13.26 9.43406 13.5356 9.24991 13.7678 9.01777C13.9999 8.78562 14.1841 8.51002 14.3097 8.20671C14.4353 7.90339 14.5 7.5783 14.5 7.25C14.5 6.9217 14.4353 6.59661 14.3097 6.29329C14.1841 5.98998 13.9999 5.71438 13.7678 5.48223C13.5356 5.25009 13.26 5.06594 12.9567 4.9403C12.6534 4.81466 12.3283 4.75 12 4.75Z" />
<path fillRule="evenodd" clipRule="evenodd" d="M5.46927 12.5545C5.95457 12.3535 6.47471 12.25 7 12.25C7.52529 12.25 8.04543 12.3535 8.53073 12.5545C9.01604 12.7555 9.45699 13.0501 9.82843 13.4216C10.1999 13.793 10.4945 14.234 10.6955 14.7193C10.8965 15.2046 11 15.7247 11 16.25C11 16.7753 10.8965 17.2954 10.6955 17.7807C10.4945 18.266 10.1999 18.707 9.82843 19.0784C9.45699 19.4499 9.01604 19.7445 8.53073 19.9455C8.04543 20.1465 7.52529 20.25 7 20.25C6.47471 20.25 5.95457 20.1465 5.46927 19.9455C4.98396 19.7445 4.54301 19.4499 4.17157 19.0784C3.80014 18.707 3.5055 18.266 3.30448 17.7807C3.10346 17.2954 3 16.7753 3 16.25C3 15.7247 3.10346 15.2046 3.30448 14.7193C3.5055 14.234 3.80014 13.793 4.17157 13.4216C4.54301 13.0501 4.98396 12.7555 5.46927 12.5545ZM7 13.75C6.67169 13.75 6.34661 13.8147 6.04329 13.9403C5.73998 14.0659 5.46438 14.2501 5.23223 14.4822C5.00009 14.7144 4.81594 14.99 4.6903 15.2933C4.56466 15.5966 4.5 15.9217 4.5 16.25C4.5 16.5783 4.56466 16.9034 4.6903 17.2067C4.81594 17.51 5.00009 17.7856 5.23223 18.0178C5.46438 18.2499 5.73998 18.4341 6.04329 18.5597C6.34661 18.6853 6.67169 18.75 7 18.75C7.3283 18.75 7.65339 18.6853 7.95671 18.5597C8.26002 18.4341 8.53562 18.2499 8.76777 18.0178C8.99991 17.7856 9.18406 17.51 9.3097 17.2067C9.43534 16.9034 9.5 16.5783 9.5 16.25C9.5 15.9217 9.43534 15.5966 9.3097 15.2933C9.18406 14.99 8.99991 14.7144 8.76777 14.4822C8.53562 14.2501 8.26002 14.0659 7.95671 13.9403C7.65339 13.8147 7.3283 13.75 7 13.75Z" />
<path fillRule="evenodd" clipRule="evenodd" d="M17 12.25C16.4747 12.25 15.9546 12.3535 15.4693 12.5545C14.984 12.7555 14.543 13.0501 14.1716 13.4216C13.8001 13.793 13.5055 14.234 13.3045 14.7193C13.1035 15.2046 13 15.7247 13 16.25C13 16.7753 13.1035 17.2954 13.3045 17.7807C13.5055 18.266 13.8001 18.707 14.1716 19.0784C14.543 19.4499 14.984 19.7445 15.4693 19.9455C15.9546 20.1465 16.4747 20.25 17 20.25C17.5253 20.25 18.0454 20.1465 18.5307 19.9455C19.016 19.7445 19.457 19.4499 19.8284 19.0784C20.1999 18.707 20.4945 18.266 20.6955 17.7807C20.8965 17.2954 21 16.7753 21 16.25C21 15.7247 20.8965 15.2046 20.6955 14.7193C20.4945 14.234 20.1999 13.793 19.8284 13.4216C19.457 13.0501 19.016 12.7555 18.5307 12.5545C18.0454 12.3535 17.5253 12.25 17 12.25ZM16.0433 13.9403C16.3466 13.8147 16.6717 13.75 17 13.75C17.3283 13.75 17.6534 13.8147 17.9567 13.9403C18.26 14.0659 18.5356 14.2501 18.7678 14.4822C18.9999 14.7144 19.1841 14.99 19.3097 15.2933C19.4353 15.5966 19.5 15.9217 19.5 16.25C19.5 16.5783 19.4353 16.9034 19.3097 17.2067C19.1841 17.51 18.9999 17.7856 18.7678 18.0178C18.5356 18.2499 18.26 18.4341 17.9567 18.5597C17.6534 18.6853 17.3283 18.75 17 18.75C16.6717 18.75 16.3466 18.6853 16.0433 18.5597C15.74 18.4341 15.4644 18.2499 15.2322 18.0178C15.0001 17.7856 14.8159 17.51 14.6903 17.2067C14.5647 16.9034 14.5 16.5783 14.5 16.25C14.5 15.9217 14.5647 15.5966 14.6903 15.2933C14.8159 14.99 15.0001 14.7144 15.2322 14.4822C15.4644 14.2501 15.74 14.0659 16.0433 13.9403Z" />
</svg>
)
export default Asana

View File

@ -0,0 +1,10 @@
import React from 'react'
const CaretDown = () => (
<svg width="24" height="24" viewBox="0 0 24 24" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
<path fillRule="evenodd" clipRule="evenodd" d="M16.5303 8.96967C16.8232 9.26256 16.8232 9.73744 16.5303 10.0303L12.5303 14.0303C12.2374 14.3232 11.7626 14.3232 11.4697 14.0303L7.46967 10.0303C7.17678 9.73744 7.17678 9.26256 7.46967 8.96967C7.76256 8.67678 8.23744 8.67678 8.53033 8.96967L12 12.4393L15.4697 8.96967C15.7626 8.67678 16.2374 8.67678 16.5303 8.96967Z"/>
</svg>
)
export default CaretDown

View File

@ -0,0 +1,13 @@
import React from 'react'
const ChartPieAlt = () => (
<svg width="24" height="24" viewBox="0 0 24 24" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
<path fillRule="evenodd" clipRule="evenodd" d="M11.25 5.78835C7.59833 6.16364 4.75 9.2492 4.75 13C4.75 17.0041 7.99594 20.25 12 20.25C15.7508 20.25 18.8364 17.4017 19.2117 13.75H12C11.5858 13.75 11.25 13.4142 11.25 13V5.78835ZM3.25 13C3.25 8.16753 7.16751 4.25002 12 4.25002C12.4142 4.25002 12.75 4.58581 12.75 5.00002V12.25H20C20.4142 12.25 20.75 12.5858 20.75 13C20.75 17.8325 16.8325 21.75 12 21.75C7.16751 21.75 3.25 17.8325 3.25 13Z" />
<path fillRule="evenodd" clipRule="evenodd" d="M15.5 4.67367V9.50002H20.3264C19.7633 7.11562 17.8844 5.2367 15.5 4.67367ZM14.998 3.06167C18.6183 3.5122 21.4878 6.38169 21.9384 10.002C22.0066 10.5501 21.5523 11 21 11H14.5C14.2239 11 14 10.7762 14 10.5V4.00002C14 3.44774 14.45 2.99347 14.998 3.06167Z" />
</svg>
)
export default ChartPieAlt

View File

@ -0,0 +1,13 @@
import React from 'react'
const Chat = () => (
<svg width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" fill="currentColor">
<path d="M8 9.49998C7.30964 9.49998 6.75 10.0596 6.75 10.75C6.75 11.4403 7.30964 12 8 12C8.69036 12 9.25 11.4403 9.25 10.75C9.25 10.0596 8.69036 9.49998 8 9.49998Z"/>
<path d="M12 9.49998C11.3096 9.49998 10.75 10.0596 10.75 10.75C10.75 11.4403 11.3096 12 12 12C12.6904 12 13.25 11.4403 13.25 10.75C13.25 10.0596 12.6904 9.49998 12 9.49998Z" />
<path d="M14.75 10.75C14.75 10.0596 15.3096 9.49998 16 9.49998C16.6904 9.49998 17.25 10.0596 17.25 10.75C17.25 11.4403 16.6904 12 16 12C15.3096 12 14.75 11.4403 14.75 10.75Z" />
<path fillRule="evenodd" clipRule="evenodd" d="M16.1007 4.59277C13.4065 4.36301 10.6983 4.34967 8.00194 4.5529L7.80871 4.56746C5.23741 4.76126 3.25 6.90409 3.25 9.48269V18C3.25 18.2639 3.38867 18.5083 3.61515 18.6437C3.84163 18.7791 4.12261 18.7855 4.35504 18.6606L8.26583 16.5589C8.44774 16.4611 8.65104 16.41 8.85756 16.41H17.834C18.9661 16.41 19.9362 15.6006 20.1392 14.4868C20.5505 12.2296 20.5829 9.91963 20.2353 7.65173L20.1329 6.9834C19.9464 5.76665 18.951 4.83584 17.7245 4.73124L16.1007 4.59277ZM8.11468 6.04865C10.731 5.85146 13.359 5.8644 15.9733 6.08734L17.597 6.22581C18.1334 6.27155 18.5686 6.67859 18.6502 7.21067L18.7526 7.879C19.075 9.98228 19.0449 12.1246 18.6635 14.218C18.5904 14.6187 18.2413 14.91 17.834 14.91H8.85756C8.40322 14.91 7.95596 15.0225 7.55575 15.2376L4.75 16.7455V9.48269C4.75 7.68878 6.13262 6.19804 7.92144 6.06322L8.11468 6.04865Z"/>
</svg>
)
export default Chat

View File

@ -0,0 +1,13 @@
import React from 'react'
const Columns = () => (
<svg width="24" height="24" viewBox="0 0 24 24" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
<path fillRule="evenodd" clipRule="evenodd" d="M18.8076 4.95724C17.4735 4.54564 16.0265 4.54564 14.6924 4.95724C14.2409 9.64156 14.2409 14.3584 14.6924 19.0428C16.0265 19.4544 17.4735 19.4544 18.8076 19.0428C19.2591 14.3584 19.2591 9.64156 18.8076 4.95724ZM20.2905 4.70875C20.7648 9.55802 20.7648 14.442 20.2905 19.2913C20.2383 19.8258 19.872 20.2751 19.3662 20.4393C17.6731 20.9889 15.8269 20.9889 14.1338 20.4393C13.628 20.2751 13.2617 19.8258 13.2095 19.2913C12.7352 14.442 12.7352 9.55802 13.2095 4.70875C13.2617 4.1742 13.628 3.72493 14.1338 3.56075C15.8269 3.01113 17.6731 3.01113 19.3662 3.56075C19.872 3.72493 20.2383 4.1742 20.2905 4.70875Z" />
<path fillRule="evenodd" clipRule="evenodd" d="M9.30761 4.95724C7.97352 4.54564 6.52648 4.54563 5.19239 4.95724C4.74092 9.64156 4.74092 14.3584 5.19239 19.0428C6.52648 19.4544 7.97352 19.4544 9.30761 19.0428C9.75907 14.3584 9.75907 9.64156 9.30761 4.95724ZM10.7905 4.70875C11.2648 9.55802 11.2648 14.442 10.7905 19.2913C10.7383 19.8258 10.372 20.2751 9.8662 20.4393C8.1731 20.9889 6.32689 20.9889 4.6338 20.4393C4.12803 20.2751 3.76174 19.8258 3.70946 19.2913C3.23523 14.442 3.23523 9.55802 3.70946 4.70875C3.76174 4.1742 4.12803 3.72493 4.6338 3.56075C6.32689 3.01113 8.17311 3.01113 9.8662 3.56075C10.372 3.72493 10.7383 4.1742 10.7905 4.70875Z" />
</svg>
)
export default Columns

View File

@ -0,0 +1,11 @@
import React from 'react'
const Cross = () => (
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M8.46447 15.5355L15.5355 8.46446" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round"/>
<path d="M8.46447 8.46447L15.5355 15.5355" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round"/>
</svg>
)
export default Cross

View File

@ -0,0 +1,14 @@
import React from 'react'
const Document = () => (
<svg width="24" height="24" viewBox="0 0 24 24" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
<path d="M15.75 13C15.75 12.5858 15.4142 12.25 15 12.25H9C8.58579 12.25 8.25 12.5858 8.25 13C8.25 13.4142 8.58579 13.75 9 13.75H15C15.4142 13.75 15.75 13.4142 15.75 13Z"/>
<path d="M15.75 17C15.75 16.5858 15.4142 16.25 15 16.25H9C8.58579 16.25 8.25 16.5858 8.25 17C8.25 17.4142 8.58579 17.75 9 17.75H15C15.4142 17.75 15.75 17.4142 15.75 17Z"/>
<path fillRule="evenodd" clipRule="evenodd" d="M7 2.25C5.48122 2.25 4.25 3.48122 4.25 5V19C4.25 20.5188 5.48122 21.75 7 21.75H17C18.5188 21.75 19.75 20.5188 19.75 19V7.96766C19.75 7.58689 19.6258 7.21651 19.3963 6.9127L16.3985 2.94504C16.0677 2.5073 15.5509 2.25 15.0022 2.25H7ZM5.75 5C5.75 4.30964 6.30964 3.75 7 3.75H14.25V8.14705C14.25 8.56126 14.5858 8.89705 15 8.89705H18.25V19C18.25 19.6904 17.6904 20.25 17 20.25H7C6.30964 20.25 5.75 19.6904 5.75 19V5Z"/>
</svg>
)
export default Document

View File

@ -0,0 +1,11 @@
import React from 'react'
const Chat = () => (
<svg width="24" height="24" viewBox="0 0 24 24" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
<path fillRule="evenodd" clipRule="evenodd" d="M2.80369 8.3533C2.52355 10.9562 2.53604 13.9582 2.92586 16.5505C3.14156 17.9849 4.31223 19.0845 5.7573 19.2102L7.26753 19.3414C10.4166 19.6152 13.5834 19.6152 16.7325 19.3414L18.2427 19.2102C19.6878 19.0845 20.8585 17.9849 21.0742 16.5505C21.464 13.9582 21.4765 10.9564 21.1963 8.35345C21.1601 8.05169 21.1194 7.75034 21.0742 7.44949C20.8585 6.0151 19.6878 4.91545 18.2427 4.78983L16.7325 4.65855C13.5834 4.38481 10.4166 4.38481 7.26753 4.65855L5.7573 4.78983C4.31223 4.91545 3.14156 6.0151 2.92586 7.44949C2.88063 7.75028 2.83991 8.05159 2.80369 8.3533ZM7.39743 6.15292C10.46 5.88669 13.54 5.88669 16.6026 6.15292L18.1128 6.2842C18.8671 6.34977 19.4782 6.92379 19.5908 7.67254C19.6025 7.7503 19.6139 7.82809 19.625 7.90592L14.064 10.9954C12.7804 11.7085 11.2196 11.7085 9.93599 10.9954L4.37505 7.90596C4.38611 7.82812 4.39749 7.75031 4.40918 7.67254C4.52178 6.92379 5.13287 6.34977 5.8872 6.2842L7.39743 6.15292ZM19.8085 9.51989C20.0025 11.7876 19.9299 14.0725 19.5908 16.3274C19.4782 17.0762 18.8671 17.6502 18.1128 17.7158L16.6026 17.8471C13.54 18.1133 10.46 18.1133 7.39743 17.8471L5.8872 17.7158C5.13287 17.6502 4.52178 17.0762 4.40918 16.3274C4.07009 14.0725 3.99753 11.7877 4.1915 9.51992L9.20752 12.3066C10.9442 13.2714 13.0558 13.2714 14.7924 12.3066L19.8085 9.51989Z"/>
</svg>
)
export default Chat

View File

@ -0,0 +1,11 @@
import React from 'react'
const Exchange = () => (
<svg width="24" height="24" viewBox="0 0 24 24" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
<path d="M7.53033 6.53033C7.82322 6.23744 7.82322 5.76256 7.53033 5.46967C7.23744 5.17678 6.76256 5.17678 6.46967 5.46967L4.46967 7.46967C4.17678 7.76256 4.17678 8.23744 4.46967 8.53033L6.46967 10.5303C6.76256 10.8232 7.23744 10.8232 7.53033 10.5303C7.82322 10.2374 7.82322 9.76256 7.53033 9.46967L6.81066 8.75H17C17.4142 8.75 17.75 8.41421 17.75 8C17.75 7.58579 17.4142 7.25 17 7.25H6.81066L7.53033 6.53033Z" />
<path d="M16.4697 13.4697C16.1768 13.7626 16.1768 14.2374 16.4697 14.5303L17.1893 15.25H7C6.58579 15.25 6.25 15.5858 6.25 16C6.25 16.4142 6.58579 16.75 7 16.75H17.1893L16.4697 17.4697C16.1768 17.7626 16.1768 18.2374 16.4697 18.5303C16.7626 18.8232 17.2374 18.8232 17.5303 18.5303L19.5303 16.5303C19.8232 16.2374 19.8232 15.7626 19.5303 15.4697L17.5303 13.4697C17.2374 13.1768 16.7626 13.1768 16.4697 13.4697Z" />
</svg>
)
export default Exchange

Some files were not shown because too many files have changed in this diff Show More