diff --git a/web/package.json b/web/package.json index 8822500e..098031b1 100644 --- a/web/package.json +++ b/web/package.json @@ -3,32 +3,32 @@ "version": "1.1.3", "private": true, "dependencies": { - "@fortawesome/fontawesome-svg-core": "^1.2.28", - "@fortawesome/free-brands-svg-icons": "^5.13.0", - "@fortawesome/free-regular-svg-icons": "^5.13.0", - "@fortawesome/free-solid-svg-icons": "^5.13.0", - "@fortawesome/react-fontawesome": "^0.1.9", - "@loadable/component": "^5.12.0", - "attr-accept": "^2.1.0", - "bootstrap": "^4.5.0", + "@fortawesome/fontawesome-svg-core": "^1.2.30", + "@fortawesome/free-brands-svg-icons": "^5.14.0", + "@fortawesome/free-regular-svg-icons": "^5.14.0", + "@fortawesome/free-solid-svg-icons": "^5.14.0", + "@fortawesome/react-fontawesome": "^0.1.11", + "@loadable/component": "^5.13.2", + "attr-accept": "^2.2.2", + "bootstrap": "^4.5.2", "chart.js": "^2.9.3", "classnames": "^2.2.6", - "echarts": "^4.7.0", - "echarts-for-react": "^2.0.15-beta.1", + "echarts": "^4.9.0", + "echarts-for-react": "^2.0.16", "element-resize-event": "^3.0.3", "emoji-mart": "^3.0.0", - "google-maps-react": "^2.0.2", + "google-maps-react": "^2.0.6", "i18next": "^19.6.3", "is_js": "^0.9.0", - "leaflet": "^1.6.0", + "leaflet": "^1.7.1", "leaflet.markercluster": "^1.4.1", "leaflet.tilelayer.colorfilter": "^1.2.5", - "lodash": "^4.17.15", - "moment": "^2.24.0", + "lodash": "^4.17.20", + "moment": "^2.28.0", "node-sass": "^4.14.1", - "plyr": "^3.5.10", + "plyr": "^3.6.2", "prism-react-renderer": "^0.1.7", - "prism-themes": "^1.3.0", + "prism-themes": "^1.4.0", "prop-types": "^15.7.2", "rc-cascader": "^1.3.0", "react": "^16.13.1", @@ -36,32 +36,32 @@ "react-beautiful-dnd": "^13.0.0", "react-bootstrap-table-next": "^3.3.5", "react-bootstrap-table2-paginator": "^2.1.2", - "react-chartjs-2": "^2.9.0", + "react-chartjs-2": "^2.10.0", "react-countup": "^4.3.3", "react-datetime": "^2.16.3", "react-dom": "^16.13.1", "react-dropzone": "^10.2.2", - "react-es6-progressbar.js": "^1.0.20", + "react-es6-progressbar.js": "^1.1.0", "react-hook-form": "^4.10.2", "react-i18next": "^11.7.0", "react-image-lightbox": "^5.1.1", "react-image-video-lightbox": "^2.0.1", - "react-leaflet": "^2.6.3", + "react-leaflet": "^2.7.0", "react-live": "^2.2.2", "react-lottie": "^1.2.3", "react-quill": "^1.3.5", "react-rating": "^2.0.5", "react-router-bootstrap": "^0.25.0", - "react-router-dom": "^5.1.2", - "react-scripts": "^3.4.1", - "react-scroll": "^1.7.16", - "react-scrollbars-custom": "^4.0.21", + "react-router-dom": "^5.2.0", + "react-scripts": "^3.4.3", + "react-scroll": "^1.8.1", + "react-scrollbars-custom": "^4.0.25", "react-select": "^3.1.0", "react-simple-code-editor": "^0.9.15", "react-slick": "^0.25.2", "react-toastify": "^5.5.0", "react-typed": "^1.2.0", - "reactstrap": "^8.4.1", + "reactstrap": "^8.6.0", "slick-carousel": "^1.8.1", "uuid": "^3.4.0" }, @@ -76,17 +76,17 @@ "extends": "react-app" }, "devDependencies": { - "browser-sync": "^2.26.7", + "browser-sync": "^2.26.12", "eslint-config-prettier": "^4.2.0", - "eslint-plugin-prettier": "^3.1.2", - "eslint-plugin-react": "^7.19.0", + "eslint-plugin-prettier": "^3.1.4", + "eslint-plugin-react": "^7.20.6", "gulp": "^4.0.2", "gulp-autoprefixer": "^6.1.0", "gulp-clean-css": "^4.3.0", "gulp-plumber": "^1.2.1", "gulp-rename": "^1.4.0", "gulp-rtlcss": "^1.4.1", - "gulp-sass": "^4.0.2", + "gulp-sass": "^4.1.0", "gulp-sourcemaps": "^2.6.5", "prettier": "1.17.1" } diff --git a/web/src/Main.js b/web/src/Main.js index 97f5e74b..aef302ea 100644 --- a/web/src/Main.js +++ b/web/src/Main.js @@ -1,47 +1,57 @@ import React, { useState, useEffect } from 'react'; import PropTypes from 'prop-types'; import AppContext from './context/Context'; +import { settings } from './config'; import toggleStylesheet from './helpers/toggleStylesheet'; import { getItemFromStore, setItemToStore, themeColors } from './helpers/utils'; import i18n from "i18next"; const Main = props => { - const [isFluid, setIsFluid] = useState(getItemFromStore('isFluid', true)); - const [isRTL, setIsRTL] = useState(getItemFromStore('isRTL', false)); - const [isDark, setIsDark] = useState(getItemFromStore('isDark', true)); - const [isTopNav, setIsTopNav] = useState(getItemFromStore('isTopNav', true)); + const [isFluid, setIsFluid] = useState(getItemFromStore('isFluid', settings.isFluid)); + const [isRTL, setIsRTL] = useState(getItemFromStore('isRTL', settings.isRTL)); + const [isDark, setIsDark] = useState(getItemFromStore('isDark', settings.isDark)); + const [isTopNav, setIsTopNav] = useState(getItemFromStore('isTopNav', settings.isTopNav)); + const [isCombo, setIsCombo] = useState(getItemFromStore('isCombo', settings.isCombo)); + const [isVertical, setIsVertical] = useState(getItemFromStore('isVertical', settings.isVertical)); const [isNavbarVerticalCollapsed, setIsNavbarVerticalCollapsed] = useState( - getItemFromStore('isNavbarVerticalCollapsed', false) + getItemFromStore('isNavbarVerticalCollapsed', settings.isNavbarVerticalCollapsed) ); - const [currency, setCurrency] = useState('$'); - const [showBurgerMenu, setShowBurgerMenu] = useState(false); + const [currency, setCurrency] = useState(settings.currency); + const [showBurgerMenu, setShowBurgerMenu] = useState(settings.showBurgerMenu); const [isLoaded, setIsLoaded] = useState(false); const [isOpenSidePanel, setIsOpenSidePanel] = useState(false); - const [navbarStyle, setNavbarStyle] = useState(getItemFromStore('navbarStyle', 'vibrant')); - const [language, setLanguage] = useState(getItemFromStore('language', 'zh_cn')); + const [navbarCollapsed, setNavbarCollapsed] = useState(false); + + const [navbarStyle, setNavbarStyle] = useState(getItemFromStore('navbarStyle', settings.navbarStyle)); + const [language, setLanguage] = useState(getItemFromStore('language', settings.language)); const toggleModal = () => setIsOpenSidePanel(prevIsOpenSidePanel => !prevIsOpenSidePanel); - const value = { isRTL, isDark, + isCombo, isFluid, setIsRTL, isTopNav, currency, setIsDark, + setIsCombo, setIsFluid, + isVertical, toggleModal, setIsTopNav, navbarStyle, setCurrency, + setIsVertical, showBurgerMenu, setNavbarStyle, language, setLanguage, isOpenSidePanel, + navbarCollapsed, setShowBurgerMenu, setIsOpenSidePanel, + setNavbarCollapsed, isNavbarVerticalCollapsed, setIsNavbarVerticalCollapsed }; @@ -77,11 +87,20 @@ const Main = props => { // eslint-disable-next-line }, [isTopNav]); + useEffect(() => { + setItemToStore('isCombo', isCombo); + // eslint-disable-next-line + }, [isCombo]); + useEffect(() => { + setItemToStore('isVertical', isVertical); + // eslint-disable-next-line + }, [isVertical]); + useEffect(() => { setItemToStore('navbarStyle', navbarStyle); // eslint-disable-next-line }, [navbarStyle]); - + useEffect(() => { setItemToStore('language', language); i18n.changeLanguage(language) diff --git a/web/src/components/bootstrap-components/Badges.js b/web/src/components/bootstrap-components/Badges.js index 449075d9..2abe0017 100644 --- a/web/src/components/bootstrap-components/Badges.js +++ b/web/src/components/bootstrap-components/Badges.js @@ -6,7 +6,7 @@ import FalconCardHeader from '../common/FalconCardHeader'; import FalconEditor from '../common/FalconEditor'; const contextualCode = `['primary', 'secondary', 'success', 'danger', 'warning', 'info', 'light', 'dark'].map((color, index) => ( - + {color} ))`; @@ -18,7 +18,7 @@ const softBadgesCode = `['primary', 'secondary', 'success', 'danger', 'warning', ))`; const softBadgesPillCode = `['primary', 'secondary', 'success', 'danger', 'warning', 'info', 'light', 'dark'].map((color, index) => ( - + {color} ))`; diff --git a/web/src/components/bootstrap-components/Cards.js b/web/src/components/bootstrap-components/Cards.js index b84489d1..edfdb868 100644 --- a/web/src/components/bootstrap-components/Cards.js +++ b/web/src/components/bootstrap-components/Cards.js @@ -34,7 +34,7 @@ const cardStyleCode = ` const basicExampleCode = ` - + Card title diff --git a/web/src/components/bootstrap-components/Combo.js b/web/src/components/bootstrap-components/Combo.js new file mode 100644 index 00000000..1a73efd5 --- /dev/null +++ b/web/src/components/bootstrap-components/Combo.js @@ -0,0 +1,63 @@ +import React, { Fragment, useContext } from 'react'; +import { Button, Card, CardBody } from 'reactstrap'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import PageHeader from '../common/PageHeader'; +import FalconCardHeader from '../common/FalconCardHeader'; +import AppContext from '../../context/Context'; + +const Combo = () => { + const { setIsOpenSidePanel } = useContext(AppContext); + + return ( + + + + + + + +

+ Combo layout uses Falcon's{' '} + + Navbar vertical{' '} + + and{' '} + + Navbar top + + . +

+

+ To enable Combo layout set isCombo to true in src/config.js file. +

+
+
+ + + + {' '} +

+ For responsive collapsing pass {`expand = {'sm | md | lg | xl'}`} prop to reactstrap{' '} + Navbar component. +

+
+
+
+ ); +}; + +export default Combo; diff --git a/web/src/components/bootstrap-components/ProgressBar.js b/web/src/components/bootstrap-components/ProgressBar.js index c0bed922..60e0025a 100644 --- a/web/src/components/bootstrap-components/ProgressBar.js +++ b/web/src/components/bootstrap-components/ProgressBar.js @@ -124,12 +124,6 @@ const ProgressBar = () => {
- - - - - - ); }; diff --git a/web/src/components/changelog/changeLogs.js b/web/src/components/changelog/changeLogs.js index 80dfb7ac..78de0fa5 100644 --- a/web/src/components/changelog/changeLogs.js +++ b/web/src/components/changelog/changeLogs.js @@ -1,8 +1,359 @@ export default [ - + { + title: `2.8.0 - Dickinson's kestrel`, + publish: '29 September, 2020', + logs: { + New: ['Navbar combo layout', 'DOC : Navbar combo Doc'], + Update: ['DOC: Documentation'], + Migration: { + Add: ['src/components/bootstrap-components/Combo.js'], + Update: [ + 'src/Main.js', + 'src/context/Context.js', + 'src/layouts/DashboardLayout.js', + 'src/components/navbar/NavbarVertical.js', + 'src/components/navbar/TopNavRightSideNavItem.js', + 'src/components/side-panel/SidePanelModal.js', + 'src/components/navbar/NavbarTopDropDownMenus.js', + 'src/components/changelog/changeLogs.js' + ] + } + } + }, + { + title: '2.7.1 - Fox Kestrel', + publish: '21 September, 2020', + logs: { + New: ['DOC : Fontawesome Doc'], + Fix: [ + 'Message page textarea hight issue', + 'Product details page review input field submit issue', + 'Customer page nameFormatter function argument destructing issue', + 'Fixes Badge component class name and Card component tag name' + ], + Migration: { + Add: ['src/components/bootstrap-component/Fontawesome.js'], + Update: [ + 'src/components/chat/content/MessageTextArea.js', + 'src/components/e-commerce/product-details/ProductDetailsFooter.js', + 'src/components/e-commerce/Customers.js' + ] + } + } + }, + { + title: '2.7.0 - Spotted Kestrels', + publish: '2 July, 2020', + logs: { + New: [ + 'Navbar Inverted in Navbar Vertical', + 'Navbar Vibrant in Navbar Vertical', + 'Navbar Card in Navbar Vertical', + 'DOC : Vertical Navbar' + ], + Migration: { + Add: ['src/components/bootstrap-component/VerticalNavbar.js'], + Update: [ + 'src/component/main.js', + 'src/component/navbar/NavbarVertical.js', + 'src/component/side-panel/SidePanelModal.js', + 'src/assets/scss/theme/_buttons.scss', + 'src/assets/scss/dark/_variables.scss', + 'src/assets/scss/theme/_variables.scss', + 'src/assets/scss/theme/_Navbar-vertical.scss' + ] + } + } + }, + { + title: '2.6.0 - Laughing', + publish: '27 june, 2020', + logs: { + New: [ + 'Page: Kanban', + 'Plugin: React Beautiful DnD', + 'Component: Cookie Notice Alert', + 'Doc: React Beautiful DnD', + 'Doc: Cookie Notice Alert', + 'Doc: React Bootstrap Table next' + ], + + Fix: ['Sidebar sticky-top on profile page.'], + + Migration: { + Add: [ + 'src/components/kanban/**/*.*', + 'src/components/bootstrap-component/cookieNotice.js', + 'src/components/plugins/ReactBeautifulDnD.js', + 'src/components/plugins/ReactBootstrapTable2.js', + 'src/assets/scss/_kanban.scss', + 'src/assets/scss/_notice.scss' + ], + Update: [ + 'src/routs.js', + 'src/helpers/utils.js', + 'src/layout/DashboardRoutes.js', + 'src/layout/DashboardLayout.js', + 'src/component/side-panel/SidePanelModal.js', + 'src/component/navbar/navbarTop.js (removed sticky-top class from Navbar)', + 'src/assets/scss/theme/_theme.scss', + 'src/assets/scss/theme/_mixed.scss', + 'src/assets/scss/theme/_modal.scss', + 'src/assets/scss/dark/_override.scss', + 'src/assets/scss/theme/_border.scss', + 'src/assets/scss/theme/_dropdown.scss', + 'src/assets/scss/theme/_scrollbar.scss', + 'src/assets/scss/theme/utilities/_hover.scss', + 'src/assets/scss/theme/utilities/_line-height.scss' + ] + } + } + }, + { + title: '2.5.0 - Chipping', + publish: '29 April, 2020', + logs: { + New: [ + 'Page: Widgets', + 'Component Page: Carousel', + 'Component Page: Spinner', + 'Component: Navber Top', + 'Component: Sidepanel Modal', + 'Dropdown On Hover', + 'Component Doc: Navbar Top ', + 'Component Doc: Sidepanel' + ], + + Fix: ['Gap between Photos card and Experience card in smaller device'], + + Migration: { + Add: [ + 'src/assets/scss/theme/_modal.scss', + 'src/components/widgets/**/*.*', + 'src/components/side-panel/**/*.*', + 'src/components/email/EmailDetailHeader.js', + 'src/components/navbar/SettingsAnimatedIcon.js', + 'src/components/navbar/TopNavRightSideNavItem.js', + 'src/components/e-commerce/OrderDetailsHeader.js', + 'src/components/bootstrap-components/NavBarTop.js', + 'src/components/navbar/LandingRightSideNavItem.js', + 'src/components/bootstrap-components/Sidepanel.js', + 'src/components/bootstrap-components/Carousel.js', + 'src/components/bootstrap-components/Spinners.js', + 'src/components/navbar/NavbarDropdownComponents.js', + 'src/components/dashboard/DashboardDepositStatus.js' + ], + Update: [ + 'src/assets/scss/theme/_theme.scss', + 'src/assets/scss/theme/_forms.scss', + 'src/assets/scss/theme/_scrollbar.scss', + 'src/assets/scss/theme/_navbar.scss', + 'src/assets/scss/theme/_navbar-top.scss', + 'src/assets/scss/theme/_navbar-vertical.scss', + 'src/assets/scss/theme/_button.scss', + 'src/assets/scss/theme/utilities/_background.scss in this file updated .bg-gradient class', + 'src/assets/scss/theme/_variables.scss updated tooltip variable', + 'src/assets/scss/theme/_documentation.scss', + + 'src/Main.js', + 'src/routes.js', + 'src/config.js', + 'src/helpers/utils.js', + 'src/components/page/People.js', + 'src/layouts/DashboardLayout.js', + 'src/components/email/Compose.js', + 'src/components/feed/FeedCard.js', + 'src/components/feed/AddToFeed.js', + 'src/components/navbar/NavbarTop.js', + 'src/components/email/EmailDetail.js', + 'src/components/feed/FeedInterest.js', + 'src/components/page/InvitePeople.js', + 'src/components/page/Notifications.js', + 'src/components/feed/BirthdayNotice.js', + 'src/components/navbar/NavbarStandard.js', + 'src/components/experience/Experience.js', + 'src/components/profile/ProfileFooter.js', + 'src/components/dashboard-alt/Weather.js', + 'src/components/navbar/NavbarDropdown.js', + 'src/components/navbar/ProfileDropdown.js', + 'src/components/dashboard-alt/TopProducts.js', + 'src/components/dashboard-alt/DashboardAlt.js', + 'src/components/dashboard-alt/SpaceWarning.js', + 'src/components/navbar/NotificationDropdown.js', + 'src/components/profile/ProfileContent.js from this file, ActivityLog Component has been updated' + ] + } + } + }, + { + title: '2.4.0 - Nankeen Kestrel', + publish: '2 April, 2020', + logs: { + New: [ + 'Page: Chat', + 'Plugin: Emoji Mart', + 'Doc: Emoji Mart' + ], + Fix: ['Dashboard recent purchases Table caret icon sorting direction issue.'], + + Migration: { + Add: [ + 'src/components/chat/**/*.*', + 'src/assets/scss/theme/_chat.scss', + 'src/assets/scss/theme/plugins/_emoji.scss' + ], + Update: [ + 'src/assets/scss/theme/_theme.scss', + 'src/assets/scss/theme/_plugins.scss', + 'src/assets/scss/theme/plugins/_react-bootstrap-table2-sort.scss' + ] + } + } + }, + { + title: '2.3.1 - Common Kestrel', + publish: '10 March, 2020', + logs: { + Fix: ['Main Navigation collapse issue when navigating between pages from mobile devices'], + Migration: { + Replace: [ + 'src/components/navbar/NavbarVerticalMenu.js', + 'src/components/common/CodeHighlight.js', + 'src/components/changelog/**/*.*' + ] + } + } + }, + { + title: '2.3.0 - Lesser Kestrel', + publish: '27 February, 2020', + logs: { + New: ['Feature: Navbar vertical collapsed'], + Update: ['Doc: Lottie', 'Doc: Dropzone'], + Migration: { + Replace: [ + 'package.json', + 'public/index.html', + 'public/css/**/*.*', + 'src/assets/scss/**/*.*', + 'src/Main.js', + 'src/helpers/toggleStylesheet.js', + 'src/components/dashboard/LeafletMap.js', + 'src/components/navbar/NavbarTop.js', + 'src/components/navbar/NavbarVertical.js', + 'src/components/navbar/NavbarVerticalMenu.js', + 'src/components/navbar/NavbarVerticalMenuItem.js', + 'src/components/changelog/**/*.*' + ], + Add: [ + 'src/components/navbar/ToggleButton.js', + 'src/components/common/CodeHighlight.js' + ] + } + } + }, + { + title: '2.2.0 - Laggar', + publish: '10 February, 2020', + logs: { + New: [ + 'Plugin: React leaflet map', + 'Plugin: leaflet-markercluster', + 'Plugin: leaflet.tilelayer.colorfilter', + 'Plugin: react-scrollbars-custom', + 'Component: Custom Scrollbar', + 'Doc: React Hook Form', + 'Doc: Custom Scroll Bar', + 'Doc: Leaflet Map', + 'Doc: Echart Map' + ], + Update: [ + 'Component: Disable Button', + 'Component: Purchases Table', + 'Component: Leaflet Map (Dashboard alt)', + 'Page: products List', + 'Doc: Echart' + ] + } + }, + { + title: '2.1.0 - Saker', + publish: '20 January, 2020', + logs: { + New: [ + 'Page: Authentication step wizard', + 'Plugin: react-hook-form' + ] + } + }, + { + title: '2.0.0 - Lanner', + publish: '01 January, 2020', + logs: { + New: [ + 'Component: Running Projects (Dashboard alt)', + 'Component: Total Sales (Dashboard alt)', + 'Mode: Dark', + 'Doc: Plyr', + 'Doc: Slick Carousel' + ], + Update: ['Doc: Echart'] + } + }, + { + title: '1.3.0 - Aplomado', + publish: '18 December, 2019', + logs: { + New: ['Page: Feed', 'Plugin: Plyr'] + } + }, + { + title: '1.2.0 - Kestrels', + publish: '11 December, 2019', + logs: { + New: [ + 'Page: Product List', + 'Page: Product Grid', + 'Page: Product Details', + 'Page: Orders', + 'Page: Order Details', + 'Page: Customers', + 'Page: Shopping Cart', + 'Page: Checkout', + 'Page: Favorite Items', + 'Counter on cart icon' + ], + Update: [ + 'CSS: Bootstrap to v4.4.1', + 'Js: utils.js', + 'Top nav badge icons' + ] + } + }, + { + title: '1.1.0 - Gyrfalcon', + publish: '04 November, 2019', + logs: { + New: [ + 'Page: Dashboard Alt', + 'Page: Inbox', + 'Page: Email detail', + 'Page: Compose', + 'Plugin: Bulk select', + 'Plugin: WYSIWYG Editor', + 'Plugin: Progressbar' + ], + Fix: ['Redirect to 404'], + Update: [ + 'Add autoprefixer configuration in package.json', + 'Update autoprefixer configuration in gulpfile.js', + 'Js: utils.js' + ] + } + }, { title: '1.0.0 - initial release', - publish: '10 July, 2020', + publish: '30 September, 2019', children: 'Nothing to see here.' } ]; diff --git a/web/src/components/chat/Chat.js b/web/src/components/chat/Chat.js index 0aec8dd8..e9b13fde 100644 --- a/web/src/components/chat/Chat.js +++ b/web/src/components/chat/Chat.js @@ -5,15 +5,17 @@ import ChatSidebar from './sidebar/ChatSidebar'; import ChatContent from './content/ChatContent'; import Flex from '../common/Flex'; -const Chat = () => ( - - - - - - - - -); +const Chat = () => { + return ( + + + + + + + + + ); +}; export default Chat; diff --git a/web/src/components/chat/content/MessageTextArea.js b/web/src/components/chat/content/MessageTextArea.js index f48a7b49..bb0018c2 100644 --- a/web/src/components/chat/content/MessageTextArea.js +++ b/web/src/components/chat/content/MessageTextArea.js @@ -1,189 +1,196 @@ -import React, { useState, useContext, useEffect } from 'react'; -import PropTypes from 'prop-types'; -import { Input, Label, Form, Button } from 'reactstrap'; -import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import 'emoji-mart/css/emoji-mart.css'; -import { Picker } from 'emoji-mart'; -import AppContext, { ChatContext } from '../../../context/Context'; -import classNames from 'classnames'; -import { getGrays } from '../../../helpers/utils'; - -const formatDate = date => { - const options = { - weekday: 'short', - day: 'numeric', - month: 'long', - year: 'numeric', - hour: 'numeric', - minute: 'numeric' - }; - - const now = date - .toLocaleString('en-US', options) - .split(',') - .map(item => item.trim()); - - return { - day: now[0], - hour: now[3], - date: now[1] + ', ' + now[2] - }; -}; - -const MessageTextArea = ({ thread }) => { - const { isDark, isRTL } = useContext(AppContext); - const { messages, messagesDispatch, threadsDispatch, textAreaInitialHeight, setTextAreaInitialHeight } = useContext( - ChatContext - ); - const [previewEmoji, setPreviewEmoji] = useState(false); - const [message, setMessage] = useState(''); - - //Emoji box hiding Controller - useEffect(() => { - const handleClickOutsideEmojiBox = e => { - if (e.target.closest('.emoji-mart') || e.target.closest('.textarea')) return; - setPreviewEmoji(false); - }; - - if (previewEmoji) { - document.addEventListener('click', handleClickOutsideEmojiBox, false); - } else { - document.removeEventListener('click', handleClickOutsideEmojiBox, false); - } - - return () => document.removeEventListener('click', handleClickOutsideEmojiBox, false); - }, [previewEmoji]); - - useEffect(() => { - //TextBox and message body height controlling - let textAreaPreviousHeight = textAreaInitialHeight; - const autoExpand = function(field) { - // Reset field height - field.style.height = '2rem'; - - // Calculate the height - const textAreaCurrentHeight = field.scrollHeight; - - if (textAreaCurrentHeight <= 160) { - if (textAreaPreviousHeight !== textAreaCurrentHeight) { - document.getElementsByClassName('card-chat-pane')[0].style.height = `calc(100% - ${textAreaCurrentHeight}px)`; - - setTextAreaInitialHeight((textAreaPreviousHeight = textAreaCurrentHeight)); - } - } - - field.style.height = textAreaCurrentHeight + 'px'; - }; - document.addEventListener( - 'input', - function(event) { - if (event.target.className === 'textarea'); - autoExpand(event.target); - }, - false - ); - }, [textAreaInitialHeight, setTextAreaInitialHeight]); - - const addEmoji = e => { - let emoji = e.native; - setMessage(message + emoji); - }; - - const handleSubmit = e => { - e.preventDefault(); - const date = new Date(); - - let newMessage = { - senderUserId: 3, - message: `${message.replace(/(?:\r\n|\r|\n)/g, '
')}`, - status: 'delivered', - time: formatDate(date) - }; - - const { content } = messages.find(({ id }) => id === thread.messagesId); - if (message) { - messagesDispatch({ - type: 'EDIT', - payload: { id: thread.messagesId, content: [...content, newMessage] }, - id: thread.messagesId - }); - - threadsDispatch({ - type: 'EDIT', - payload: thread, - id: thread.id, - isUpdatedStart: true - }); - } - - setMessage(''); - - document.getElementsByClassName('textarea')[0].style.height = '2rem'; - document.getElementsByClassName('card-chat-pane')[0].style.height = `calc(100% - 2rem)`; - }; - - return ( -
- - - - setMessage(target.value)} - style={{ - height: '2rem', - maxHeight: '10rem', - paddingRight: isRTL ? '0.75rem' : '7rem', - paddingLeft: isRTL ? '7rem' : '0.75rem' - }} - /> - setPreviewEmoji(!previewEmoji)} - /> - {previewEmoji && ( - - )} - - - ); -}; - -MessageTextArea.propTypes = { - thread: PropTypes.object.isRequired -}; - -export default MessageTextArea; +import React, { useState, useContext, useEffect, useRef } from 'react'; +import PropTypes from 'prop-types'; +import { Input, Label, Form, Button } from 'reactstrap'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import 'emoji-mart/css/emoji-mart.css'; +import { Picker } from 'emoji-mart'; +import AppContext, { ChatContext } from '../../../context/Context'; +import classNames from 'classnames'; +import { getGrays } from '../../../helpers/utils'; + +const formatDate = date => { + const options = { + weekday: 'short', + day: 'numeric', + month: 'long', + year: 'numeric', + hour: 'numeric', + minute: 'numeric' + }; + + const now = date + .toLocaleString('en-US', options) + .split(',') + .map(item => item.trim()); + + return { + day: now[0], + hour: now[3], + date: now[1] + ', ' + now[2] + }; +}; + +const MessageTextArea = ({ thread }) => { + const { isDark, isRTL } = useContext(AppContext); + const { messages, messagesDispatch, threadsDispatch, textAreaInitialHeight, setTextAreaInitialHeight } = useContext( + ChatContext + ); + const [previewEmoji, setPreviewEmoji] = useState(false); + const [message, setMessage] = useState(''); + + const isMountedRef = useRef(null); + + //Emoji box hiding Controller + useEffect(() => { + const handleClickOutsideEmojiBox = e => { + if (e.target.closest('.emoji-mart') || e.target.closest('.textarea')) return; + setPreviewEmoji(false); + }; + + if (previewEmoji) { + document.addEventListener('click', handleClickOutsideEmojiBox, false); + } else { + document.removeEventListener('click', handleClickOutsideEmojiBox, false); + } + + return () => document.removeEventListener('click', handleClickOutsideEmojiBox, false); + }, [previewEmoji]); + + useEffect(() => { + //TextBox and message body height controlling + isMountedRef.current = true; + let textAreaPreviousHeight = textAreaInitialHeight; + const autoExpand = function(field) { + // Reset field height + field.style.height = '2rem'; + + // Calculate the height + const textAreaCurrentHeight = field.scrollHeight; + + if (textAreaCurrentHeight <= 160 && document.querySelector('.card-chat-pane')) { + if (textAreaPreviousHeight !== textAreaCurrentHeight && isMountedRef.current) { + document.querySelector('.card-chat-pane').style.height = `calc(100% - ${textAreaCurrentHeight}px)`; + setTextAreaInitialHeight((textAreaPreviousHeight = textAreaCurrentHeight)); + } + } + + field.style.height = textAreaCurrentHeight + 'px'; + }; + if (document.querySelector('.textarea')) { + document.addEventListener( + 'input', + function(event) { + if (event.target.className === 'textarea'); + autoExpand(event.target); + }, + false + ); + } + return () => { + isMountedRef.current = false; + }; + }, [textAreaInitialHeight, setTextAreaInitialHeight]); + + const addEmoji = e => { + let emoji = e.native; + setMessage(message + emoji); + }; + + const handleSubmit = e => { + e.preventDefault(); + const date = new Date(); + + let newMessage = { + senderUserId: 3, + message: `${message.replace(/(?:\r\n|\r|\n)/g, '
')}`, + status: 'delivered', + time: formatDate(date) + }; + + const { content } = messages.find(({ id }) => id === thread.messagesId); + if (message) { + messagesDispatch({ + type: 'EDIT', + payload: { id: thread.messagesId, content: [...content, newMessage] }, + id: thread.messagesId + }); + + threadsDispatch({ + type: 'EDIT', + payload: thread, + id: thread.id, + isUpdatedStart: true + }); + } + + setMessage(''); + + document.querySelector('.textarea').style.height = '2rem'; + document.querySelector('.card-chat-pane').style.height = `calc(100% - 2rem)`; + }; + + return ( +
+ + + + setMessage(target.value)} + style={{ + height: '2rem', + maxHeight: '10rem', + paddingRight: isRTL ? '0.75rem' : '7rem', + paddingLeft: isRTL ? '7rem' : '0.75rem' + }} + /> + setPreviewEmoji(!previewEmoji)} + /> + {previewEmoji && ( + + )} + + + ); +}; + +MessageTextArea.propTypes = { + thread: PropTypes.object.isRequired +}; + +export default MessageTextArea; diff --git a/web/src/components/common/FalconProgress.js b/web/src/components/common/FalconProgress.js new file mode 100644 index 00000000..ef378897 --- /dev/null +++ b/web/src/components/common/FalconProgress.js @@ -0,0 +1,37 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import FalconProgressBar from './FalconProgressBar'; + +const FalconProgress = ({ value, className, style, color, barStyle, barClassName, multi, children, bar }) => { + return ( + <> + {bar === true ? ( + + ) : ( +
+ {multi ? ( + children + ) : ( + + )} +
+ )} + + ); +}; + +FalconProgress.propTypes = { + value: PropTypes.oneOfType([PropTypes.number, PropTypes.string]).isRequired, + color: PropTypes.string, + barStyle: PropTypes.object, + className: PropTypes.string, + barClassName: PropTypes.string, + style: PropTypes.object, + multi: PropTypes.bool +}; + +FalconProgress.defaultProps = { + value: 0 +}; + +export default FalconProgress; diff --git a/web/src/components/common/FalconProgressBar.js b/web/src/components/common/FalconProgressBar.js new file mode 100644 index 00000000..80085d7d --- /dev/null +++ b/web/src/components/common/FalconProgressBar.js @@ -0,0 +1,14 @@ +import React from 'react'; + +const FalconProgressBar = ({ className, barStyle, value, color }) => ( +
+); + +export default FalconProgressBar; diff --git a/web/src/components/dashboard-alt/BestSellingProduct.js b/web/src/components/dashboard-alt/BestSellingProduct.js index 7a2bd30f..1cafc6ef 100644 --- a/web/src/components/dashboard-alt/BestSellingProduct.js +++ b/web/src/components/dashboard-alt/BestSellingProduct.js @@ -1,10 +1,11 @@ import React, { useContext } from 'react'; import PropTypes from 'prop-types'; import classNames from 'classnames'; -import { Media, Progress } from 'reactstrap'; +import { Media } from 'reactstrap'; import Flex from '../common/Flex'; import AppContext from '../../context/Context'; import { Link } from 'react-router-dom'; +import FalconProgress from '../common/FalconProgress'; const getProductItemCalculatedData = (unit, price, totalPrice) => { const productTotalPrice = unit * price; @@ -37,14 +38,15 @@ const BestSellingProduct = ({ product, totalPrice, isLast }) => { {productTotalPrice} - - + +
{percentage}%
diff --git a/web/src/components/dashboard-alt/RunningProject.js b/web/src/components/dashboard-alt/RunningProject.js index cda72f0e..90c1e1b4 100644 --- a/web/src/components/dashboard-alt/RunningProject.js +++ b/web/src/components/dashboard-alt/RunningProject.js @@ -1,8 +1,9 @@ import React from 'react'; import PropTypes from 'prop-types'; import classNames from 'classnames'; -import { Media, Progress, Row, Col, Badge } from 'reactstrap'; +import { Media, Row, Col, Badge } from 'reactstrap'; import Flex from '../common/Flex'; +import FalconProgress from '../common/FalconProgress'; const RunningProject = ({ project, isLast }) => { const { color, progress, time, title } = project; @@ -34,12 +35,11 @@ const RunningProject = ({ project, isLast }) => {
{time}
- diff --git a/web/src/components/dashboard-alt/StorageStatus.js b/web/src/components/dashboard-alt/StorageStatus.js index 3c0cf104..5bd8af53 100644 --- a/web/src/components/dashboard-alt/StorageStatus.js +++ b/web/src/components/dashboard-alt/StorageStatus.js @@ -1,10 +1,11 @@ import React from 'react'; import PropTypes from 'prop-types'; -import { Card, CardBody, Progress, Row } from 'reactstrap'; +import { Card, CardBody, Row } from 'reactstrap'; import Flex from '../common/Flex'; import { isIterableArray } from '../../helpers/utils'; import StorageStatusProgressBar from './StorageStatusProgressBar'; import StorageStatusDot from './StorageStatusDot'; +import FalconProgress from '../common/FalconProgress'; const StorageStatus = ({ data, className }) => { const totalStorage = data.map(d => d.size).reduce((total, currentValue) => total + currentValue, 0); @@ -18,17 +19,19 @@ const StorageStatus = ({ data, className }) => { Using Storage {totalStorage - freeStorage} MB of{' '} {Math.round(totalStorage / 1024)} GB - + {isIterableArray(data) && - data.map((d, index) => ( - - ))} - + data.map((d, index) => { + return ( + + ); + })} + {isIterableArray(data) && data.map((d, index) => ( diff --git a/web/src/components/dashboard-alt/StorageStatusProgressBar.js b/web/src/components/dashboard-alt/StorageStatusProgressBar.js index cd0e8ea2..42ef3a24 100644 --- a/web/src/components/dashboard-alt/StorageStatusProgressBar.js +++ b/web/src/components/dashboard-alt/StorageStatusProgressBar.js @@ -1,13 +1,13 @@ import React from 'react'; import PropTypes from 'prop-types'; -import { Progress } from 'reactstrap'; import classNames from 'classnames'; +import FalconProgress from '../common/FalconProgressBar'; const StorageStatusProgressBar = ({ color, percentage, isLast }) => ( - ); diff --git a/web/src/components/documentation/GettingStarted.js b/web/src/components/documentation/GettingStarted.js index 1389a329..f71c9850 100644 --- a/web/src/components/documentation/GettingStarted.js +++ b/web/src/components/documentation/GettingStarted.js @@ -1,5 +1,6 @@ import React, { Fragment } from 'react'; -import { Card, CardBody } from 'reactstrap'; +import { Card, CardBody, CardHeader, NavLink } from 'reactstrap'; +import CodeHighlight from '../common/CodeHighlight'; import FalconCardHeader from '../common/FalconCardHeader'; import PageHeader from '../common/PageHeader'; @@ -101,6 +102,40 @@ const GettingStarted = () => (

+ + + + Settings configuration + + + +

+ Control side panel settings from one place. Go to src/config.js file and set your setting + configuration. +

+ +
+
diff --git a/web/src/components/e-commerce/Customers.js b/web/src/components/e-commerce/Customers.js index 0cbd8b61..9a741aee 100644 --- a/web/src/components/e-commerce/Customers.js +++ b/web/src/components/e-commerce/Customers.js @@ -25,16 +25,18 @@ import { getPaginationArray } from '../../helpers/utils'; import customers from '../../data/e-commerce/customers'; -const nameFormatter = (dataField, { name, avatar }: row) => ( - - - - -
{name}
+const nameFormatter = (dataField, { avatar, name }) => { + return ( + + + + +
{name}
+
-
- -); + + ); +}; const emailFormatter = email => {email}; const phoneFormatter = phone => {phone}; diff --git a/web/src/components/e-commerce/product-details/ProductDetailsFooter.js b/web/src/components/e-commerce/product-details/ProductDetailsFooter.js index 4a66eae7..67f8b2ae 100644 --- a/web/src/components/e-commerce/product-details/ProductDetailsFooter.js +++ b/web/src/components/e-commerce/product-details/ProductDetailsFooter.js @@ -171,18 +171,13 @@ const ProductDetailsFooter = () => { - console.log(target.value)} /> + console.log(value)} /> - console.log(target.value)} type="email" /> + console.log(value)} type="email" /> - console.log(target.value)} - type="textarea" - rows="2" - /> + console.log(value)} type="textarea" rows="2" />
- - {/* */} ); diff --git a/web/src/components/navbar/SettingsAnimatedIcon.js b/web/src/components/navbar/SettingsAnimatedIcon.js index 98a68936..ba8948d3 100644 --- a/web/src/components/navbar/SettingsAnimatedIcon.js +++ b/web/src/components/navbar/SettingsAnimatedIcon.js @@ -1,13 +1,11 @@ import React, { useContext } from 'react'; import AppContext from '../../context/Context'; -import { Link } from 'react-router-dom'; const SettingsAnimatedIcon = () => { const { toggleModal } = useContext(AppContext); return ( - { toggleModal(); }} @@ -23,7 +21,7 @@ const SettingsAnimatedIcon = () => { - + ); }; diff --git a/web/src/components/navbar/TopNavRightSideNavItem.js b/web/src/components/navbar/TopNavRightSideNavItem.js index c790803c..c0b2154e 100644 --- a/web/src/components/navbar/TopNavRightSideNavItem.js +++ b/web/src/components/navbar/TopNavRightSideNavItem.js @@ -15,7 +15,17 @@ const TopNavRightSideNavItem = () => { - + {isTopNav && ( + + + + + + Changelog + + + )} + diff --git a/web/src/components/plugins/FontAwesome.js b/web/src/components/plugins/FontAwesome.js index 0bd32b19..7016910f 100644 --- a/web/src/components/plugins/FontAwesome.js +++ b/web/src/components/plugins/FontAwesome.js @@ -4,6 +4,7 @@ import { Button, Card, CardBody } from 'reactstrap'; import PageHeader from '../common/PageHeader'; import FalconEditor from '../common/FalconEditor'; import FalconCardHeader from '../common/FalconCardHeader'; +import CodeHighlight from '../common/CodeHighlight'; const FontAwesome = () => ( @@ -24,11 +25,44 @@ const FontAwesome = () => ( - - + + +

+ For adding new icon, go to src/helpers/initFA.js file. We initialize all fontawesome icons here. + Import your icon from your desired icon module and then pass it to library.add() function. +

+ +

+ For better understanding you can visit{' '} + fontawesome usage +

+
+
+ + + +

+ Now in your component file just import the FontAwesomeIcon component, and when you use it, supply + the icon prop an icon name as a string +

+ +
`} + code={``} + scope={{ FontAwesomeIcon }} + language="jsx" + /> +
+ `} scope={{ FontAwesomeIcon }} language="jsx" /> diff --git a/web/src/components/plugins/Leaflet.js b/web/src/components/plugins/Leaflet.js index a07cc36d..7c9d1679 100644 --- a/web/src/components/plugins/Leaflet.js +++ b/web/src/components/plugins/Leaflet.js @@ -45,7 +45,7 @@ const leafletCode = `function LeafletMap () { : ['bright:101%', 'contrast:101%', 'hue:23deg', 'saturate:225%']; - if(mapWidht){ + if(mapWidth){ useEffect(() => { L.tileLayer .colorFilter('https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}{r}.png', { @@ -63,7 +63,7 @@ const leafletCode = `function LeafletMap () { maxZoom={18} zoomSnap={0.5} className="h-100 w-100" - style={{ width:mapWidht, minHeight: 300 }} + style={{ width:mapWidth, minHeight: 300 }} ref={map} > @@ -75,17 +75,17 @@ const leafletCode = `function LeafletMap () { const Leaflet = () => { const { isDark } = useContext(AppContext); let map = useRef(null); - const [mapWidht, setMapwidth] = useState(); + const [mapWidth, setMapWidth] = useState(); const egMap = useRef(); useEffect(() => { const timer = setTimeout(() => { - setMapwidth(egMap.current.offsetWidth); + setMapWidth(egMap.current.offsetWidth); }, 500); return () => { clearTimeout(timer); }; - }, [isDark, mapWidht]); + }, [isDark, mapWidth]); return ( @@ -107,7 +107,7 @@ const Leaflet = () => { diff --git a/web/src/components/side-panel/SidePanelModal.js b/web/src/components/side-panel/SidePanelModal.js index 3efe73a1..9947ecf1 100644 --- a/web/src/components/side-panel/SidePanelModal.js +++ b/web/src/components/side-panel/SidePanelModal.js @@ -24,6 +24,7 @@ import { withTranslation } from 'react-i18next'; const SidePanelModal = ({ autoShow, showOnce, autoShowDelay, cookieExpireTime, path, t }) => { const { + isCombo, isOpenSidePanel, toggleModal, isFluid, @@ -34,9 +35,11 @@ const SidePanelModal = ({ autoShow, showOnce, autoShowDelay, cookieExpireTime, p setIsDark, isTopNav, setIsTopNav, - setIsOpenSidePanel + setIsOpenSidePanel, + setIsCombo, + isVertical, + setIsVertical } = useContext(AppContext); - const isKanban = getPageName('kanban'); useEffect(() => { @@ -49,7 +52,6 @@ const SidePanelModal = ({ autoShow, showOnce, autoShowDelay, cookieExpireTime, p }, autoShowDelay); } }, [autoShow, showOnce, setIsOpenSidePanel, autoShowDelay, cookieExpireTime]); - return ( setIsTopNav(!target.checked)} + label="Vertical" + name="NavBarPositionRadioButton" + checked={!isCombo && isVertical} + onChange={({ target }) => { + setIsVertical(target.checked); + setIsTopNav(!target.checked); + setIsCombo(!target.checked); + }} inline /> setIsTopNav(target.checked)} + label="Top" + name="NavBarPositionRadioButton" + checked={!isCombo && isTopNav} + onChange={({ target }) => { + setIsTopNav(target.checked); + setIsVertical(!target.checked); + setIsCombo(!target.checked); + }} + inline + /> + { + setIsCombo(target.checked); + setIsTopNav(target.checked); + setIsVertical(target.checked); + }} inline />
-
- {t('Vertical Navbar Style')}{' '} - - new - -
+
{t('Vertical Navbar Style')}

{t('Switch between styles for your vertical navbar')}

diff --git a/web/src/config.js b/web/src/config.js index 62b49935..db538afe 100644 --- a/web/src/config.js +++ b/web/src/config.js @@ -3,3 +3,19 @@ export const navbarBreakPoint = 'xl'; // Vertical navbar breakpoint export const topNavbarBreakpoint = 'lg'; //export const APIBaseURL = 'http://127.0.0.1:8000'; export const APIBaseURL = window.location.protocol+"//"+window.location.hostname+":"+window.location.port+"/api"; +export const settings = { + isFluid: true, + isRTL: false, + isDark: true, + isTopNav: true, + isVertical: false, + get isCombo() { + return this.isVertical && this.isTopNav; + }, + showBurgerMenu: false, // controls showing vertical nav on mobile + currency: '$', + isNavbarVerticalCollapsed: false, + navbarStyle: 'transparent', + language: 'zh_cn' +}; +export default { version, navbarBreakPoint, topNavbarBreakpoint, settings, APIBaseURL }; \ No newline at end of file diff --git a/web/src/context/Context.js b/web/src/context/Context.js index 0d7fdc3d..c57e5509 100644 --- a/web/src/context/Context.js +++ b/web/src/context/Context.js @@ -1,15 +1,7 @@ import { createContext } from 'react'; +import { settings } from '../config'; -const AppContext = createContext({ - isFluid: true, - isRTL: false, - isDark: true, - showBurgerMenu: false, // controls showing vertical nav on mobile - currency: '$', - isNavbarVerticalCollapsed: false, - navbarStyle: 'vibrant', - language: 'zh_cn', -}); +const AppContext = createContext(settings); export const EmailContext = createContext({ emails: [] }); diff --git a/web/src/layouts/DashboardLayout.js b/web/src/layouts/DashboardLayout.js index 18566ac0..14ad61ac 100644 --- a/web/src/layouts/DashboardLayout.js +++ b/web/src/layouts/DashboardLayout.js @@ -17,7 +17,7 @@ import { getPageName } from '../helpers/utils'; const DashboardRoutes = loadable(() => import('./MyEMSRoutes')); const DashboardLayout = ({ location }) => { - const { isFluid, isTopNav, navbarStyle } = useContext(AppContext); + const { isFluid, isVertical, navbarStyle } = useContext(AppContext); const isKanban = getPageName('kanban'); @@ -31,7 +31,7 @@ const DashboardLayout = ({ location }) => { return (
- {!isTopNav && } + {isVertical && }
diff --git a/web/src/layouts/DashboardRoutes.js b/web/src/layouts/DashboardRoutes.js index 05080acc..59c6a050 100644 --- a/web/src/layouts/DashboardRoutes.js +++ b/web/src/layouts/DashboardRoutes.js @@ -42,6 +42,7 @@ import ProgressBar from '../components/bootstrap-components/ProgressBar'; import Tables from '../components/bootstrap-components/Tables'; import Tooltips from '../components/bootstrap-components/Tooltips'; import NavBarTop from '../components/bootstrap-components/NavBarTop'; +import Combo from '../components/bootstrap-components/Combo'; import VerticalNavbar from '../components/bootstrap-components/VerticalNavbar'; import Sidepanel from '../components/bootstrap-components/Sidepanel'; import CookieNotice from '../components/bootstrap-components/CookieNotice'; @@ -191,6 +192,7 @@ const DashboardRoutes = () => ( + @@ -229,7 +231,7 @@ const DashboardRoutes = () => ( - + diff --git a/web/src/layouts/Layout.js b/web/src/layouts/Layout.js index 58858ff2..32234a22 100644 --- a/web/src/layouts/Layout.js +++ b/web/src/layouts/Layout.js @@ -26,11 +26,11 @@ const Layout = () => { }> - + } position={toast.POSITION.BOTTOM_LEFT} />