upgraded Web UI template to 2.8.0

pull/42/MERGE
13621160019@163.com 2021-06-24 21:54:48 +08:00
parent b69460007b
commit b2c18260a9
30 changed files with 969 additions and 351 deletions

56
web/package.json vendored
View File

@ -3,32 +3,32 @@
"version": "1.1.3", "version": "1.1.3",
"private": true, "private": true,
"dependencies": { "dependencies": {
"@fortawesome/fontawesome-svg-core": "^1.2.28", "@fortawesome/fontawesome-svg-core": "^1.2.30",
"@fortawesome/free-brands-svg-icons": "^5.13.0", "@fortawesome/free-brands-svg-icons": "^5.14.0",
"@fortawesome/free-regular-svg-icons": "^5.13.0", "@fortawesome/free-regular-svg-icons": "^5.14.0",
"@fortawesome/free-solid-svg-icons": "^5.13.0", "@fortawesome/free-solid-svg-icons": "^5.14.0",
"@fortawesome/react-fontawesome": "^0.1.9", "@fortawesome/react-fontawesome": "^0.1.11",
"@loadable/component": "^5.12.0", "@loadable/component": "^5.13.2",
"attr-accept": "^2.1.0", "attr-accept": "^2.2.2",
"bootstrap": "^4.5.0", "bootstrap": "^4.5.2",
"chart.js": "^2.9.3", "chart.js": "^2.9.3",
"classnames": "^2.2.6", "classnames": "^2.2.6",
"echarts": "^4.7.0", "echarts": "^4.9.0",
"echarts-for-react": "^2.0.15-beta.1", "echarts-for-react": "^2.0.16",
"element-resize-event": "^3.0.3", "element-resize-event": "^3.0.3",
"emoji-mart": "^3.0.0", "emoji-mart": "^3.0.0",
"google-maps-react": "^2.0.2", "google-maps-react": "^2.0.6",
"i18next": "^19.6.3", "i18next": "^19.6.3",
"is_js": "^0.9.0", "is_js": "^0.9.0",
"leaflet": "^1.6.0", "leaflet": "^1.7.1",
"leaflet.markercluster": "^1.4.1", "leaflet.markercluster": "^1.4.1",
"leaflet.tilelayer.colorfilter": "^1.2.5", "leaflet.tilelayer.colorfilter": "^1.2.5",
"lodash": "^4.17.15", "lodash": "^4.17.20",
"moment": "^2.24.0", "moment": "^2.28.0",
"node-sass": "^4.14.1", "node-sass": "^4.14.1",
"plyr": "^3.5.10", "plyr": "^3.6.2",
"prism-react-renderer": "^0.1.7", "prism-react-renderer": "^0.1.7",
"prism-themes": "^1.3.0", "prism-themes": "^1.4.0",
"prop-types": "^15.7.2", "prop-types": "^15.7.2",
"rc-cascader": "^1.3.0", "rc-cascader": "^1.3.0",
"react": "^16.13.1", "react": "^16.13.1",
@ -36,32 +36,32 @@
"react-beautiful-dnd": "^13.0.0", "react-beautiful-dnd": "^13.0.0",
"react-bootstrap-table-next": "^3.3.5", "react-bootstrap-table-next": "^3.3.5",
"react-bootstrap-table2-paginator": "^2.1.2", "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-countup": "^4.3.3",
"react-datetime": "^2.16.3", "react-datetime": "^2.16.3",
"react-dom": "^16.13.1", "react-dom": "^16.13.1",
"react-dropzone": "^10.2.2", "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-hook-form": "^4.10.2",
"react-i18next": "^11.7.0", "react-i18next": "^11.7.0",
"react-image-lightbox": "^5.1.1", "react-image-lightbox": "^5.1.1",
"react-image-video-lightbox": "^2.0.1", "react-image-video-lightbox": "^2.0.1",
"react-leaflet": "^2.6.3", "react-leaflet": "^2.7.0",
"react-live": "^2.2.2", "react-live": "^2.2.2",
"react-lottie": "^1.2.3", "react-lottie": "^1.2.3",
"react-quill": "^1.3.5", "react-quill": "^1.3.5",
"react-rating": "^2.0.5", "react-rating": "^2.0.5",
"react-router-bootstrap": "^0.25.0", "react-router-bootstrap": "^0.25.0",
"react-router-dom": "^5.1.2", "react-router-dom": "^5.2.0",
"react-scripts": "^3.4.1", "react-scripts": "^3.4.3",
"react-scroll": "^1.7.16", "react-scroll": "^1.8.1",
"react-scrollbars-custom": "^4.0.21", "react-scrollbars-custom": "^4.0.25",
"react-select": "^3.1.0", "react-select": "^3.1.0",
"react-simple-code-editor": "^0.9.15", "react-simple-code-editor": "^0.9.15",
"react-slick": "^0.25.2", "react-slick": "^0.25.2",
"react-toastify": "^5.5.0", "react-toastify": "^5.5.0",
"react-typed": "^1.2.0", "react-typed": "^1.2.0",
"reactstrap": "^8.4.1", "reactstrap": "^8.6.0",
"slick-carousel": "^1.8.1", "slick-carousel": "^1.8.1",
"uuid": "^3.4.0" "uuid": "^3.4.0"
}, },
@ -76,17 +76,17 @@
"extends": "react-app" "extends": "react-app"
}, },
"devDependencies": { "devDependencies": {
"browser-sync": "^2.26.7", "browser-sync": "^2.26.12",
"eslint-config-prettier": "^4.2.0", "eslint-config-prettier": "^4.2.0",
"eslint-plugin-prettier": "^3.1.2", "eslint-plugin-prettier": "^3.1.4",
"eslint-plugin-react": "^7.19.0", "eslint-plugin-react": "^7.20.6",
"gulp": "^4.0.2", "gulp": "^4.0.2",
"gulp-autoprefixer": "^6.1.0", "gulp-autoprefixer": "^6.1.0",
"gulp-clean-css": "^4.3.0", "gulp-clean-css": "^4.3.0",
"gulp-plumber": "^1.2.1", "gulp-plumber": "^1.2.1",
"gulp-rename": "^1.4.0", "gulp-rename": "^1.4.0",
"gulp-rtlcss": "^1.4.1", "gulp-rtlcss": "^1.4.1",
"gulp-sass": "^4.0.2", "gulp-sass": "^4.1.0",
"gulp-sourcemaps": "^2.6.5", "gulp-sourcemaps": "^2.6.5",
"prettier": "1.17.1" "prettier": "1.17.1"
} }

View File

@ -1,47 +1,57 @@
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import AppContext from './context/Context'; import AppContext from './context/Context';
import { settings } from './config';
import toggleStylesheet from './helpers/toggleStylesheet'; import toggleStylesheet from './helpers/toggleStylesheet';
import { getItemFromStore, setItemToStore, themeColors } from './helpers/utils'; import { getItemFromStore, setItemToStore, themeColors } from './helpers/utils';
import i18n from "i18next"; import i18n from "i18next";
const Main = props => { const Main = props => {
const [isFluid, setIsFluid] = useState(getItemFromStore('isFluid', true)); const [isFluid, setIsFluid] = useState(getItemFromStore('isFluid', settings.isFluid));
const [isRTL, setIsRTL] = useState(getItemFromStore('isRTL', false)); const [isRTL, setIsRTL] = useState(getItemFromStore('isRTL', settings.isRTL));
const [isDark, setIsDark] = useState(getItemFromStore('isDark', true)); const [isDark, setIsDark] = useState(getItemFromStore('isDark', settings.isDark));
const [isTopNav, setIsTopNav] = useState(getItemFromStore('isTopNav', true)); 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( const [isNavbarVerticalCollapsed, setIsNavbarVerticalCollapsed] = useState(
getItemFromStore('isNavbarVerticalCollapsed', false) getItemFromStore('isNavbarVerticalCollapsed', settings.isNavbarVerticalCollapsed)
); );
const [currency, setCurrency] = useState('$'); const [currency, setCurrency] = useState(settings.currency);
const [showBurgerMenu, setShowBurgerMenu] = useState(false); const [showBurgerMenu, setShowBurgerMenu] = useState(settings.showBurgerMenu);
const [isLoaded, setIsLoaded] = useState(false); const [isLoaded, setIsLoaded] = useState(false);
const [isOpenSidePanel, setIsOpenSidePanel] = useState(false); const [isOpenSidePanel, setIsOpenSidePanel] = useState(false);
const [navbarStyle, setNavbarStyle] = useState(getItemFromStore('navbarStyle', 'vibrant')); const [navbarCollapsed, setNavbarCollapsed] = useState(false);
const [language, setLanguage] = useState(getItemFromStore('language', 'zh_cn'));
const [navbarStyle, setNavbarStyle] = useState(getItemFromStore('navbarStyle', settings.navbarStyle));
const [language, setLanguage] = useState(getItemFromStore('language', settings.language));
const toggleModal = () => setIsOpenSidePanel(prevIsOpenSidePanel => !prevIsOpenSidePanel); const toggleModal = () => setIsOpenSidePanel(prevIsOpenSidePanel => !prevIsOpenSidePanel);
const value = { const value = {
isRTL, isRTL,
isDark, isDark,
isCombo,
isFluid, isFluid,
setIsRTL, setIsRTL,
isTopNav, isTopNav,
currency, currency,
setIsDark, setIsDark,
setIsCombo,
setIsFluid, setIsFluid,
isVertical,
toggleModal, toggleModal,
setIsTopNav, setIsTopNav,
navbarStyle, navbarStyle,
setCurrency, setCurrency,
setIsVertical,
showBurgerMenu, showBurgerMenu,
setNavbarStyle, setNavbarStyle,
language, language,
setLanguage, setLanguage,
isOpenSidePanel, isOpenSidePanel,
navbarCollapsed,
setShowBurgerMenu, setShowBurgerMenu,
setIsOpenSidePanel, setIsOpenSidePanel,
setNavbarCollapsed,
isNavbarVerticalCollapsed, isNavbarVerticalCollapsed,
setIsNavbarVerticalCollapsed setIsNavbarVerticalCollapsed
}; };
@ -77,11 +87,20 @@ const Main = props => {
// eslint-disable-next-line // eslint-disable-next-line
}, [isTopNav]); }, [isTopNav]);
useEffect(() => {
setItemToStore('isCombo', isCombo);
// eslint-disable-next-line
}, [isCombo]);
useEffect(() => {
setItemToStore('isVertical', isVertical);
// eslint-disable-next-line
}, [isVertical]);
useEffect(() => { useEffect(() => {
setItemToStore('navbarStyle', navbarStyle); setItemToStore('navbarStyle', navbarStyle);
// eslint-disable-next-line // eslint-disable-next-line
}, [navbarStyle]); }, [navbarStyle]);
useEffect(() => { useEffect(() => {
setItemToStore('language', language); setItemToStore('language', language);
i18n.changeLanguage(language) i18n.changeLanguage(language)

View File

@ -6,7 +6,7 @@ import FalconCardHeader from '../common/FalconCardHeader';
import FalconEditor from '../common/FalconEditor'; import FalconEditor from '../common/FalconEditor';
const contextualCode = `['primary', 'secondary', 'success', 'danger', 'warning', 'info', 'light', 'dark'].map((color, index) => ( const contextualCode = `['primary', 'secondary', 'success', 'danger', 'warning', 'info', 'light', 'dark'].map((color, index) => (
<Badge color={color} key={index} className="mr-2"> <Badge color={color} key={index} className="mr-2" >
{color} {color}
</Badge> </Badge>
))`; ))`;
@ -18,7 +18,7 @@ const softBadgesCode = `['primary', 'secondary', 'success', 'danger', 'warning',
))`; ))`;
const softBadgesPillCode = `['primary', 'secondary', 'success', 'danger', 'warning', 'info', 'light', 'dark'].map((color, index) => ( const softBadgesPillCode = `['primary', 'secondary', 'success', 'danger', 'warning', 'info', 'light', 'dark'].map((color, index) => (
<Badge color={'badge-pill badge-soft-'+color} key={index} className="mr-2"> <Badge color={'soft-'+color} key={index} className="mr-2" pill>
{color} {color}
</Badge> </Badge>
))`; ))`;

View File

@ -34,7 +34,7 @@ const cardStyleCode = `<CardColumns>
const basicExampleCode = `<Card style={{width: '20rem'}}> const basicExampleCode = `<Card style={{width: '20rem'}}>
<CardImg src={generic1} top /> <CardImg src={generic1} top />
<CardBody> <CardBody>
<CardTitle tag="h5" tag="h5"> <CardTitle tag="h5">
Card title Card title
</CardTitle> </CardTitle>
<CardText tag="p"> <CardText tag="p">

View File

@ -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 (
<Fragment>
<PageHeader
title="Combo Nav"
description="Combo Nav is an additional layout system of Falcon where you can place both Navbar Top and Navbar Vertical in a same page."
className="mb-3"
>
<Button
onClick={() => {
setIsOpenSidePanel(pre => !pre);
}}
color="link"
size="sm"
className="pl-0"
>
Toggle Combo Nav on Side panel
<FontAwesomeIcon icon="chevron-right" className="ml-1 fs--2" />
</Button>
</PageHeader>
<Card className="mb-3">
<FalconCardHeader title="Supported Content" light={false} />
<CardBody className="bg-light">
<p>
Combo layout uses Falcon's{' '}
<a href="/components/navbar-vertical" target="_blank">
Navbar vertical{' '}
</a>
and{' '}
<a href="/components/navbar-top" target="_blank">
Navbar top
</a>
.
</p>
<p className="mb-0">
To enable Combo layout set <code>isCombo</code> to true in <code>src/config.js</code> file.
</p>
</CardBody>
</Card>
<Card className="mb-3">
<FalconCardHeader title="Behaviors" light={false} />
<CardBody className="bg-light">
{' '}
<p className="mb-0">
For responsive collapsing pass <code>{`expand = {'sm | md | lg | xl'}`}</code> prop to reactstrap{' '}
<code>Navbar</code> component.
</p>
</CardBody>
</Card>
</Fragment>
);
};
export default Combo;

View File

@ -124,12 +124,6 @@ const ProgressBar = () => {
<FalconEditor code={stripedExampleCode} /> <FalconEditor code={stripedExampleCode} />
</CardBody> </CardBody>
</Card> </Card>
<Card className="mb-3">
<FalconCardHeader title="Animated" light={false} />
<CardBody className="bg-light">
<FalconEditor code={animatedExampleCode} language="jsx" />
</CardBody>
</Card>
</Fragment> </Fragment>
); );
}; };

View File

@ -1,8 +1,359 @@
export default [ export default [
{
title: `2.8.0 - Dickinson's kestrel`,
publish: '29 September, 2020',
logs: {
New: ['Navbar combo layout', '<strong>DOC</strong> : Navbar combo Doc'],
Update: ['<strong>DOC</strong>: Documentation'],
Migration: {
Add: ['<code>src/components/bootstrap-components/Combo.js</code>'],
Update: [
'<code>src/Main.js</code>',
'<code>src/context/Context.js</code>',
'<code>src/layouts/DashboardLayout.js</code>',
'<code>src/components/navbar/NavbarVertical.js</code>',
'<code>src/components/navbar/TopNavRightSideNavItem.js</code>',
'<code>src/components/side-panel/SidePanelModal.js</code>',
'<code>src/components/navbar/NavbarTopDropDownMenus.js</code>',
'<code>src/components/changelog/changeLogs.js</code>'
]
}
}
},
{
title: '2.7.1 - Fox Kestrel',
publish: '21 September, 2020',
logs: {
New: ['<strong>DOC</strong> : Fontawesome Doc'],
Fix: [
'Message page textarea hight issue',
'Product details page review input field submit issue',
'Customer page nameFormatter function argument destructing issue',
'Fixes <code>Badge</code> component class name and <code>Card</code> component tag name'
],
Migration: {
Add: ['<code>src/components/bootstrap-component/Fontawesome.js</code>'],
Update: [
'<code>src/components/chat/content/MessageTextArea.js</code>',
'<code>src/components/e-commerce/product-details/ProductDetailsFooter.js</code>',
'<code>src/components/e-commerce/Customers.js</code>'
]
}
}
},
{
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',
'<strong>DOC</strong> : Vertical Navbar'
],
Migration: {
Add: ['<code>src/components/bootstrap-component/VerticalNavbar.js</code>'],
Update: [
'<code>src/component/main.js</code>',
'<code>src/component/navbar/NavbarVertical.js</code>',
'<code>src/component/side-panel/SidePanelModal.js</code>',
'<code>src/assets/scss/theme/_buttons.scss</code>',
'<code>src/assets/scss/dark/_variables.scss</code>',
'<code>src/assets/scss/theme/_variables.scss</code>',
'<code>src/assets/scss/theme/_Navbar-vertical.scss</code>'
]
}
}
},
{
title: '2.6.0 - Laughing',
publish: '27 june, 2020',
logs: {
New: [
'<strong>Page</strong>: Kanban',
'<strong>Plugin</strong>: <code>React Beautiful DnD</code>',
'<strong>Component</strong>: Cookie Notice Alert',
'<strong>Doc</strong>: React Beautiful DnD',
'<strong>Doc</strong>: Cookie Notice Alert',
'<strong>Doc</strong>: React Bootstrap Table next'
],
Fix: ['Sidebar sticky-top on profile page.'],
Migration: {
Add: [
'<code>src/components/kanban/**/*.*</code>',
'<code>src/components/bootstrap-component/cookieNotice.js</code>',
'<code>src/components/plugins/ReactBeautifulDnD.js</code>',
'<code>src/components/plugins/ReactBootstrapTable2.js</code>',
'<code>src/assets/scss/_kanban.scss</code>',
'<code>src/assets/scss/_notice.scss</code>'
],
Update: [
'<code>src/routs.js</code>',
'<code>src/helpers/utils.js</code>',
'<code>src/layout/DashboardRoutes.js</code>',
'<code>src/layout/DashboardLayout.js</code>',
'<code>src/component/side-panel/SidePanelModal.js</code>',
'<code>src/component/navbar/navbarTop.js</code> (removed <code>sticky-top</code> class from Navbar)',
'<code>src/assets/scss/theme/_theme.scss</code>',
'<code>src/assets/scss/theme/_mixed.scss</code>',
'<code>src/assets/scss/theme/_modal.scss</code>',
'<code>src/assets/scss/dark/_override.scss</code>',
'<code>src/assets/scss/theme/_border.scss</code>',
'<code>src/assets/scss/theme/_dropdown.scss</code>',
'<code>src/assets/scss/theme/_scrollbar.scss</code>',
'<code>src/assets/scss/theme/utilities/_hover.scss</code>',
'<code>src/assets/scss/theme/utilities/_line-height.scss</code>'
]
}
}
},
{
title: '2.5.0 - Chipping',
publish: '29 April, 2020',
logs: {
New: [
'<strong>Page</strong>: <code>Widgets</code>',
'<strong>Component Page</strong>: <code>Carousel</code>',
'<strong>Component Page</strong>: <code>Spinner</code>',
'<strong>Component</strong>: <code>Navber Top</code>',
'<strong>Component</strong>: <code>Sidepanel Modal</code>',
'<strong>Dropdown On Hover</strong>',
'<strong>Component Doc</strong>: <code>Navbar Top</code> ',
'<strong>Component Doc</strong>: <code>Sidepanel</code>'
],
Fix: ['Gap between Photos card and Experience card in smaller device'],
Migration: {
Add: [
'<code>src/assets/scss/theme/_modal.scss</code>',
'<code>src/components/widgets/**/*.*</code>',
'<code>src/components/side-panel/**/*.*</code>',
'<code>src/components/email/EmailDetailHeader.js</code>',
'<code>src/components/navbar/SettingsAnimatedIcon.js</code>',
'<code>src/components/navbar/TopNavRightSideNavItem.js</code>',
'<code>src/components/e-commerce/OrderDetailsHeader.js</code>',
'<code>src/components/bootstrap-components/NavBarTop.js</code>',
'<code>src/components/navbar/LandingRightSideNavItem.js</code>',
'<code>src/components/bootstrap-components/Sidepanel.js</code>',
'<code>src/components/bootstrap-components/Carousel.js</code>',
'<code>src/components/bootstrap-components/Spinners.js</code>',
'<code>src/components/navbar/NavbarDropdownComponents.js</code>',
'<code>src/components/dashboard/DashboardDepositStatus.js</code>'
],
Update: [
'<code>src/assets/scss/theme/_theme.scss</code>',
'<code>src/assets/scss/theme/_forms.scss</code>',
'<code>src/assets/scss/theme/_scrollbar.scss</code>',
'<code>src/assets/scss/theme/_navbar.scss</code>',
'<code>src/assets/scss/theme/_navbar-top.scss</code>',
'<code>src/assets/scss/theme/_navbar-vertical.scss</code>',
'<code>src/assets/scss/theme/_button.scss</code>',
'<code>src/assets/scss/theme/utilities/_background.scss</code> in this file updated <code>.bg-gradient</code> class',
'<code>src/assets/scss/theme/_variables.scss</code> updated tooltip variable',
'<code>src/assets/scss/theme/_documentation.scss</code>',
'<code>src/Main.js</code>',
'<code>src/routes.js</code>',
'<code>src/config.js</code>',
'<code>src/helpers/utils.js</code>',
'<code>src/components/page/People.js</code>',
'<code>src/layouts/DashboardLayout.js</code>',
'<code>src/components/email/Compose.js</code>',
'<code>src/components/feed/FeedCard.js</code>',
'<code>src/components/feed/AddToFeed.js</code>',
'<code>src/components/navbar/NavbarTop.js</code>',
'<code>src/components/email/EmailDetail.js</code>',
'<code>src/components/feed/FeedInterest.js</code>',
'<code>src/components/page/InvitePeople.js</code>',
'<code>src/components/page/Notifications.js</code>',
'<code>src/components/feed/BirthdayNotice.js</code>',
'<code>src/components/navbar/NavbarStandard.js</code>',
'<code>src/components/experience/Experience.js</code>',
'<code>src/components/profile/ProfileFooter.js</code>',
'<code>src/components/dashboard-alt/Weather.js</code>',
'<code>src/components/navbar/NavbarDropdown.js</code>',
'<code>src/components/navbar/ProfileDropdown.js</code>',
'<code>src/components/dashboard-alt/TopProducts.js</code>',
'<code>src/components/dashboard-alt/DashboardAlt.js</code>',
'<code>src/components/dashboard-alt/SpaceWarning.js</code>',
'<code>src/components/navbar/NotificationDropdown.js</code>',
'<code>src/components/profile/ProfileContent.js</code> from this file, <code>ActivityLog</code> Component has been updated'
]
}
}
},
{
title: '2.4.0 - Nankeen Kestrel',
publish: '2 April, 2020',
logs: {
New: [
'<strong>Page</strong>: Chat',
'<strong>Plugin</strong>: <code>Emoji Mart</code>',
'<strong>Doc</strong>: Emoji Mart'
],
Fix: ['Dashboard recent purchases Table caret icon sorting direction issue.'],
Migration: {
Add: [
'<code>src/components/chat/**/*.*</code>',
'<code>src/assets/scss/theme/_chat.scss</code>',
'<code>src/assets/scss/theme/plugins/_emoji.scss</code>'
],
Update: [
'<code>src/assets/scss/theme/_theme.scss</code>',
'<code>src/assets/scss/theme/_plugins.scss</code>',
'<code>src/assets/scss/theme/plugins/_react-bootstrap-table2-sort.scss</code>'
]
}
}
},
{
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: [
'<code>src/components/navbar/NavbarVerticalMenu.js</code>',
'<code>src/components/common/CodeHighlight.js</code>',
'<code>src/components/changelog/**/*.*</code>'
]
}
}
},
{
title: '2.3.0 - Lesser Kestrel',
publish: '27 February, 2020',
logs: {
New: ['<strong>Feature</strong>: Navbar vertical collapsed'],
Update: ['<strong>Doc</strong>: Lottie', '<strong>Doc</strong>: Dropzone'],
Migration: {
Replace: [
'<code>package.json</code>',
'<code>public/index.html</code>',
'<code>public/css/**/*.*</code>',
'<code>src/assets/scss/**/*.*</code>',
'<code>src/Main.js</code>',
'<code>src/helpers/toggleStylesheet.js</code>',
'<code>src/components/dashboard/LeafletMap.js</code>',
'<code>src/components/navbar/NavbarTop.js</code>',
'<code>src/components/navbar/NavbarVertical.js</code>',
'<code>src/components/navbar/NavbarVerticalMenu.js</code>',
'<code>src/components/navbar/NavbarVerticalMenuItem.js</code>',
'<code>src/components/changelog/**/*.*</code>'
],
Add: [
'<code>src/components/navbar/ToggleButton.js</code>',
'<code>src/components/common/CodeHighlight.js</code>'
]
}
}
},
{
title: '2.2.0 - Laggar',
publish: '10 February, 2020',
logs: {
New: [
'<strong>Plugin</strong>: <code>React leaflet map</code>',
'<strong>Plugin</strong>: <code>leaflet-markercluster</code>',
'<strong>Plugin</strong>: <code>leaflet.tilelayer.colorfilter</code>',
'<strong>Plugin</strong>: <code>react-scrollbars-custom</code>',
'<strong>Component</strong>: Custom Scrollbar',
'<strong>Doc</strong>: React Hook Form',
'<strong>Doc</strong>: Custom Scroll Bar',
'<strong>Doc</strong>: Leaflet Map',
'<strong>Doc</strong>: Echart Map'
],
Update: [
'<strong>Component</strong>: Disable Button',
'<strong>Component</strong>: Purchases Table',
'<strong>Component</strong>: Leaflet Map (Dashboard alt)',
'<strong>Page</strong>: products List',
'<strong>Doc</strong>: Echart'
]
}
},
{
title: '2.1.0 - Saker',
publish: '20 January, 2020',
logs: {
New: [
'<strong>Page</strong>: Authentication step wizard',
'<strong>Plugin</strong>: <code>react-hook-form</code>'
]
}
},
{
title: '2.0.0 - Lanner',
publish: '01 January, 2020',
logs: {
New: [
'<strong>Component</strong>: Running Projects (Dashboard alt)',
'<strong>Component</strong>: Total Sales (Dashboard alt)',
'<strong>Mode</strong>: Dark',
'<strong>Doc</strong>: Plyr',
'<strong>Doc</strong>: Slick Carousel'
],
Update: ['<strong>Doc</strong>: Echart']
}
},
{
title: '1.3.0 - Aplomado',
publish: '18 December, 2019',
logs: {
New: ['<strong>Page</strong>: Feed', '<strong>Plugin</strong>: Plyr']
}
},
{
title: '1.2.0 - Kestrels',
publish: '11 December, 2019',
logs: {
New: [
'<strong>Page</strong>: Product List',
'<strong>Page</strong>: Product Grid',
'<strong>Page</strong>: Product Details',
'<strong>Page</strong>: Orders',
'<strong>Page</strong>: Order Details',
'<strong>Page</strong>: Customers',
'<strong>Page</strong>: Shopping Cart',
'<strong>Page</strong>: Checkout',
'<strong>Page</strong>: Favorite Items',
'Counter on cart icon'
],
Update: [
'<strong>CSS</strong>: Bootstrap to <code>v4.4.1</code>',
'<strong>Js</strong>: <code>utils.js</code>',
'Top nav badge icons'
]
}
},
{
title: '1.1.0 - Gyrfalcon',
publish: '04 November, 2019',
logs: {
New: [
'<strong>Page</strong>: Dashboard Alt',
'<strong>Page</strong>: Inbox',
'<strong>Page</strong>: Email detail',
'<strong>Page</strong>: Compose',
'<strong>Plugin</strong>: Bulk select',
'<strong>Plugin</strong>: WYSIWYG Editor',
'<strong>Plugin</strong>: Progressbar'
],
Fix: ['Redirect to 404'],
Update: [
'Add autoprefixer configuration in <code>package.json</code>',
'Update autoprefixer configuration in <code>gulpfile.js</code>',
'<strong>Js</strong>: <code>utils.js</code>'
]
}
},
{ {
title: '1.0.0 - initial release', title: '1.0.0 - initial release',
publish: '10 July, 2020', publish: '30 September, 2019',
children: 'Nothing to see here.' children: 'Nothing to see here.'
} }
]; ];

View File

@ -5,15 +5,17 @@ import ChatSidebar from './sidebar/ChatSidebar';
import ChatContent from './content/ChatContent'; import ChatContent from './content/ChatContent';
import Flex from '../common/Flex'; import Flex from '../common/Flex';
const Chat = () => ( const Chat = () => {
<ChatProvider> return (
<Card className="card-chat"> <ChatProvider>
<CardBody tag={Flex} className="p-0 h-100"> <Card className="card-chat">
<ChatSidebar /> <CardBody tag={Flex} className="p-0 h-100">
<ChatContent /> <ChatSidebar />
</CardBody> <ChatContent />
</Card> </CardBody>
</ChatProvider> </Card>
); </ChatProvider>
);
};
export default Chat; export default Chat;

View File

@ -1,189 +1,196 @@
import React, { useState, useContext, useEffect } from 'react'; import React, { useState, useContext, useEffect, useRef } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { Input, Label, Form, Button } from 'reactstrap'; import { Input, Label, Form, Button } from 'reactstrap';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import 'emoji-mart/css/emoji-mart.css'; import 'emoji-mart/css/emoji-mart.css';
import { Picker } from 'emoji-mart'; import { Picker } from 'emoji-mart';
import AppContext, { ChatContext } from '../../../context/Context'; import AppContext, { ChatContext } from '../../../context/Context';
import classNames from 'classnames'; import classNames from 'classnames';
import { getGrays } from '../../../helpers/utils'; import { getGrays } from '../../../helpers/utils';
const formatDate = date => { const formatDate = date => {
const options = { const options = {
weekday: 'short', weekday: 'short',
day: 'numeric', day: 'numeric',
month: 'long', month: 'long',
year: 'numeric', year: 'numeric',
hour: 'numeric', hour: 'numeric',
minute: 'numeric' minute: 'numeric'
}; };
const now = date const now = date
.toLocaleString('en-US', options) .toLocaleString('en-US', options)
.split(',') .split(',')
.map(item => item.trim()); .map(item => item.trim());
return { return {
day: now[0], day: now[0],
hour: now[3], hour: now[3],
date: now[1] + ', ' + now[2] date: now[1] + ', ' + now[2]
}; };
}; };
const MessageTextArea = ({ thread }) => { const MessageTextArea = ({ thread }) => {
const { isDark, isRTL } = useContext(AppContext); const { isDark, isRTL } = useContext(AppContext);
const { messages, messagesDispatch, threadsDispatch, textAreaInitialHeight, setTextAreaInitialHeight } = useContext( const { messages, messagesDispatch, threadsDispatch, textAreaInitialHeight, setTextAreaInitialHeight } = useContext(
ChatContext ChatContext
); );
const [previewEmoji, setPreviewEmoji] = useState(false); const [previewEmoji, setPreviewEmoji] = useState(false);
const [message, setMessage] = useState(''); const [message, setMessage] = useState('');
//Emoji box hiding Controller const isMountedRef = useRef(null);
useEffect(() => {
const handleClickOutsideEmojiBox = e => { //Emoji box hiding Controller
if (e.target.closest('.emoji-mart') || e.target.closest('.textarea')) return; useEffect(() => {
setPreviewEmoji(false); const handleClickOutsideEmojiBox = e => {
}; if (e.target.closest('.emoji-mart') || e.target.closest('.textarea')) return;
setPreviewEmoji(false);
if (previewEmoji) { };
document.addEventListener('click', handleClickOutsideEmojiBox, false);
} else { if (previewEmoji) {
document.removeEventListener('click', handleClickOutsideEmojiBox, false); document.addEventListener('click', handleClickOutsideEmojiBox, false);
} } else {
document.removeEventListener('click', handleClickOutsideEmojiBox, false);
return () => document.removeEventListener('click', handleClickOutsideEmojiBox, false); }
}, [previewEmoji]);
return () => document.removeEventListener('click', handleClickOutsideEmojiBox, false);
useEffect(() => { }, [previewEmoji]);
//TextBox and message body height controlling
let textAreaPreviousHeight = textAreaInitialHeight; useEffect(() => {
const autoExpand = function(field) { //TextBox and message body height controlling
// Reset field height isMountedRef.current = true;
field.style.height = '2rem'; let textAreaPreviousHeight = textAreaInitialHeight;
const autoExpand = function(field) {
// Calculate the height // Reset field height
const textAreaCurrentHeight = field.scrollHeight; field.style.height = '2rem';
if (textAreaCurrentHeight <= 160) { // Calculate the height
if (textAreaPreviousHeight !== textAreaCurrentHeight) { const textAreaCurrentHeight = field.scrollHeight;
document.getElementsByClassName('card-chat-pane')[0].style.height = `calc(100% - ${textAreaCurrentHeight}px)`;
if (textAreaCurrentHeight <= 160 && document.querySelector('.card-chat-pane')) {
setTextAreaInitialHeight((textAreaPreviousHeight = textAreaCurrentHeight)); if (textAreaPreviousHeight !== textAreaCurrentHeight && isMountedRef.current) {
} document.querySelector('.card-chat-pane').style.height = `calc(100% - ${textAreaCurrentHeight}px)`;
} setTextAreaInitialHeight((textAreaPreviousHeight = textAreaCurrentHeight));
}
field.style.height = textAreaCurrentHeight + 'px'; }
};
document.addEventListener( field.style.height = textAreaCurrentHeight + 'px';
'input', };
function(event) { if (document.querySelector('.textarea')) {
if (event.target.className === 'textarea'); document.addEventListener(
autoExpand(event.target); 'input',
}, function(event) {
false if (event.target.className === 'textarea');
); autoExpand(event.target);
}, [textAreaInitialHeight, setTextAreaInitialHeight]); },
false
const addEmoji = e => { );
let emoji = e.native; }
setMessage(message + emoji); return () => {
}; isMountedRef.current = false;
};
const handleSubmit = e => { }, [textAreaInitialHeight, setTextAreaInitialHeight]);
e.preventDefault();
const date = new Date(); const addEmoji = e => {
let emoji = e.native;
let newMessage = { setMessage(message + emoji);
senderUserId: 3, };
message: `${message.replace(/(?:\r\n|\r|\n)/g, '<br>')}`,
status: 'delivered', const handleSubmit = e => {
time: formatDate(date) e.preventDefault();
}; const date = new Date();
const { content } = messages.find(({ id }) => id === thread.messagesId); let newMessage = {
if (message) { senderUserId: 3,
messagesDispatch({ message: `${message.replace(/(?:\r\n|\r|\n)/g, '<br>')}`,
type: 'EDIT', status: 'delivered',
payload: { id: thread.messagesId, content: [...content, newMessage] }, time: formatDate(date)
id: thread.messagesId };
});
const { content } = messages.find(({ id }) => id === thread.messagesId);
threadsDispatch({ if (message) {
type: 'EDIT', messagesDispatch({
payload: thread, type: 'EDIT',
id: thread.id, payload: { id: thread.messagesId, content: [...content, newMessage] },
isUpdatedStart: true id: thread.messagesId
}); });
}
threadsDispatch({
setMessage(''); type: 'EDIT',
payload: thread,
document.getElementsByClassName('textarea')[0].style.height = '2rem'; id: thread.id,
document.getElementsByClassName('card-chat-pane')[0].style.height = `calc(100% - 2rem)`; isUpdatedStart: true
}; });
}
return (
<Form className="chat-editor-area bg-white" onSubmit={handleSubmit}> setMessage('');
<Input className="d-none" type="file" id="chat-file-upload" />
<Label for="chat-file-upload" className="mb-0 p-1 chat-file-upload cursor-pointer"> document.querySelector('.textarea').style.height = '2rem';
<FontAwesomeIcon icon="paperclip" /> document.querySelector('.card-chat-pane').style.height = `calc(100% - 2rem)`;
</Label> };
<Input return (
className="border-0 outline-none shadow-none resize-none textarea bg-white" <Form className="chat-editor-area bg-white" onSubmit={handleSubmit}>
type="textarea" <Input className="d-none" type="file" id="chat-file-upload" />
placeholder="Type your message" <Label for="chat-file-upload" className="mb-0 p-1 chat-file-upload cursor-pointer">
bsSize="sm" <FontAwesomeIcon icon="paperclip" />
value={message} </Label>
onChange={({ target }) => setMessage(target.value)}
style={{ <Input
height: '2rem', className="border-0 outline-none shadow-none resize-none textarea bg-white"
maxHeight: '10rem', type="textarea"
paddingRight: isRTL ? '0.75rem' : '7rem', placeholder="Type your message"
paddingLeft: isRTL ? '7rem' : '0.75rem' bsSize="sm"
}} value={message}
/> onChange={({ target }) => setMessage(target.value)}
<FontAwesomeIcon style={{
icon={['far', 'laugh-beam']} height: '2rem',
transform="grow-5" maxHeight: '10rem',
className="emoji-icon" paddingRight: isRTL ? '0.75rem' : '7rem',
onClick={() => setPreviewEmoji(!previewEmoji)} paddingLeft: isRTL ? '7rem' : '0.75rem'
/> }}
{previewEmoji && ( />
<Picker <FontAwesomeIcon
set="google" icon={['far', 'laugh-beam']}
onSelect={addEmoji} transform="grow-5"
sheetSize={20} className="emoji-icon"
style={{ onClick={() => setPreviewEmoji(!previewEmoji)}
position: 'absolute', />
bottom: '100%', {previewEmoji && (
left: isRTL ? '2%' : 'auto', <Picker
right: isRTL ? 'auto' : '2%', set="google"
padding: 0, onSelect={addEmoji}
zIndex: 1, sheetSize={20}
backgroundColor: getGrays(isDark)[100] style={{
}} position: 'absolute',
theme={isDark ? 'dark' : 'light'} bottom: '100%',
showPreview={false} left: isRTL ? '2%' : 'auto',
showSkinTones={false} right: isRTL ? 'auto' : '2%',
/> padding: 0,
)} zIndex: 1,
<Button backgroundColor: getGrays(isDark)[100]
color="transparent" }}
size="sm" theme={isDark ? 'dark' : 'light'}
className={classNames(`btn-send outline-none ml-1`, { showPreview={false}
'text-primary': message.length > 0 showSkinTones={false}
})} />
type="submit" )}
> <Button
Send color="transparent"
</Button> size="sm"
</Form> className={classNames(`btn-send outline-none ml-1`, {
); 'text-primary': message.length > 0
}; })}
type="submit"
MessageTextArea.propTypes = { >
thread: PropTypes.object.isRequired Send
}; </Button>
</Form>
export default MessageTextArea; );
};
MessageTextArea.propTypes = {
thread: PropTypes.object.isRequired
};
export default MessageTextArea;

View File

@ -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 ? (
<FalconProgressBar />
) : (
<div className={`progress ${className ?? ''} bg-${color}`} style={style}>
{multi ? (
children
) : (
<FalconProgressBar value={value} className={barClassName} color={color} style={barStyle} />
)}
</div>
)}
</>
);
};
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;

View File

@ -0,0 +1,14 @@
import React from 'react';
const FalconProgressBar = ({ className, barStyle, value, color }) => (
<div
className={`progress-bar ${className ?? ''} bg-${color}`}
style={{ ...barStyle, width: `${value}%` }}
role="progressbar"
aria-valuenow={value}
aria-valuemin="0"
aria-valuemax="100"
/>
);
export default FalconProgressBar;

View File

@ -1,10 +1,11 @@
import React, { useContext } from 'react'; import React, { useContext } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import classNames from 'classnames'; import classNames from 'classnames';
import { Media, Progress } from 'reactstrap'; import { Media } from 'reactstrap';
import Flex from '../common/Flex'; import Flex from '../common/Flex';
import AppContext from '../../context/Context'; import AppContext from '../../context/Context';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import FalconProgress from '../common/FalconProgress';
const getProductItemCalculatedData = (unit, price, totalPrice) => { const getProductItemCalculatedData = (unit, price, totalPrice) => {
const productTotalPrice = unit * price; const productTotalPrice = unit * price;
@ -37,14 +38,15 @@ const BestSellingProduct = ({ product, totalPrice, isLast }) => {
{productTotalPrice} {productTotalPrice}
</td> </td>
<td className="align-middle pr-card"> <td className="align-middle pr-card">
<Flex align="center"> <Flex align="center" justify="between">
<Progress <FalconProgress
value={percentage} value={percentage}
color="primary" color="primary"
className="w-100 mr-2 rounded-soft bg-200" className="w-100 rounded-soft bg-200"
barClassName="rounded-capsule" barClassName="rounded-capsule"
style={{ height: '5px' }} style={{ height: 5, maxWidth: 54 }}
/> />
<div className="font-weight-semi-bold ml-2">{percentage}%</div> <div className="font-weight-semi-bold ml-2">{percentage}%</div>
</Flex> </Flex>
</td> </td>

View File

@ -1,8 +1,9 @@
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import classNames from 'classnames'; 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 Flex from '../common/Flex';
import FalconProgress from '../common/FalconProgress';
const RunningProject = ({ project, isLast }) => { const RunningProject = ({ project, isLast }) => {
const { color, progress, time, title } = project; const { color, progress, time, title } = project;
@ -34,12 +35,11 @@ const RunningProject = ({ project, isLast }) => {
<div className="fs--1 font-weight-semi-bold">{time}</div> <div className="fs--1 font-weight-semi-bold">{time}</div>
</Col> </Col>
<Col xs="5" className="pr-card"> <Col xs="5" className="pr-card">
<Progress <FalconProgress
value={progress} value={progress}
color="primary" color="primary"
className="w-100 rounded-soft bg-200"
barClassName="rounded-capsule"
style={{ height: '5px' }} style={{ height: '5px' }}
className="w-100 rounded-soft bg-200"
/> />
</Col> </Col>
</Row> </Row>

View File

@ -1,10 +1,11 @@
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { Card, CardBody, Progress, Row } from 'reactstrap'; import { Card, CardBody, Row } from 'reactstrap';
import Flex from '../common/Flex'; import Flex from '../common/Flex';
import { isIterableArray } from '../../helpers/utils'; import { isIterableArray } from '../../helpers/utils';
import StorageStatusProgressBar from './StorageStatusProgressBar'; import StorageStatusProgressBar from './StorageStatusProgressBar';
import StorageStatusDot from './StorageStatusDot'; import StorageStatusDot from './StorageStatusDot';
import FalconProgress from '../common/FalconProgress';
const StorageStatus = ({ data, className }) => { const StorageStatus = ({ data, className }) => {
const totalStorage = data.map(d => d.size).reduce((total, currentValue) => total + currentValue, 0); const totalStorage = data.map(d => d.size).reduce((total, currentValue) => total + currentValue, 0);
@ -18,17 +19,19 @@ const StorageStatus = ({ data, className }) => {
Using Storage <strong className="text-dark">{totalStorage - freeStorage} MB </strong>of{' '} Using Storage <strong className="text-dark">{totalStorage - freeStorage} MB </strong>of{' '}
{Math.round(totalStorage / 1024)} GB {Math.round(totalStorage / 1024)} GB
</h6> </h6>
<Progress multi className="rounded-soft mb-3" style={{ height: 10 }}> <FalconProgress multi className="rounded-soft mb-3" style={{ height: '10px' }}>
{isIterableArray(data) && {isIterableArray(data) &&
data.map((d, index) => ( data.map((d, index) => {
<StorageStatusProgressBar return (
{...d} <StorageStatusProgressBar
percentage={(d.size * 100) / totalStorage} {...d}
isLast={data.length - 1 === index} percentage={(d.size * 100) / totalStorage}
key={index} isLast={data.length - 1 === index}
/> key={index}
))} />
</Progress> );
})}
</FalconProgress>
<Row className="fs--1 font-weight-semi-bold text-500"> <Row className="fs--1 font-weight-semi-bold text-500">
{isIterableArray(data) && {isIterableArray(data) &&
data.map((d, index) => ( data.map((d, index) => (

View File

@ -1,13 +1,13 @@
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { Progress } from 'reactstrap';
import classNames from 'classnames'; import classNames from 'classnames';
import FalconProgress from '../common/FalconProgressBar';
const StorageStatusProgressBar = ({ color, percentage, isLast }) => ( const StorageStatusProgressBar = ({ color, percentage, isLast }) => (
<Progress <FalconProgress
bar bar
color={color}
value={percentage} value={percentage}
color={color}
className={classNames({ 'border-right border-white border-2x': !isLast })} className={classNames({ 'border-right border-white border-2x': !isLast })}
/> />
); );

View File

@ -1,5 +1,6 @@
import React, { Fragment } from 'react'; 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 FalconCardHeader from '../common/FalconCardHeader';
import PageHeader from '../common/PageHeader'; import PageHeader from '../common/PageHeader';
@ -101,6 +102,40 @@ const GettingStarted = () => (
</p> </p>
</CardBody> </CardBody>
</Card> </Card>
<Card className="mb-3" id="setting-config">
<CardHeader className="bg-light">
<NavLink href="#setting-config" className="font-weight-semi-bold fs-1 p-0 text-900">
Settings configuration
</NavLink>
</CardHeader>
<CardBody>
<p>
Control side panel settings from one place. Go to <code>src/config.js</code> file and set your setting
configuration.
</p>
<CodeHighlight
code={`export const version = '2.8.0';
export const navbarBreakPoint = 'xl'; // Vertical navbar breakpoint
export const topNavbarBreakpoint = 'lg';
export const settings = {
isFluid: false,
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, // toggle vertical navbar collapse
navbarStyle: 'transparent'
};
export default { version, navbarBreakPoint, topNavbarBreakpoint, settings };`}
language="jsx"
/>
</CardBody>
</Card>
<Card className="mb-3"> <Card className="mb-3">
<FalconCardHeader title="Contents" /> <FalconCardHeader title="Contents" />
<CardBody> <CardBody>

View File

@ -25,16 +25,18 @@ import { getPaginationArray } from '../../helpers/utils';
import customers from '../../data/e-commerce/customers'; import customers from '../../data/e-commerce/customers';
const nameFormatter = (dataField, { name, avatar }: row) => ( const nameFormatter = (dataField, { avatar, name }) => {
<Link to="/pages/customer-details"> return (
<Media tag={Flex} align="center"> <Link to="/pages/customer-details">
<Avatar {...avatar} /> <Media tag={Flex} align="center">
<Media body className="ml-2"> <Avatar {...avatar} />
<h5 className="mb-0 fs--1">{name}</h5> <Media body className="ml-2">
<h5 className="mb-0 fs--1">{name}</h5>
</Media>
</Media> </Media>
</Media> </Link>
</Link> );
); };
const emailFormatter = email => <a href={`mailto:${email}`}>{email}</a>; const emailFormatter = email => <a href={`mailto:${email}`}>{email}</a>;
const phoneFormatter = phone => <a href={`tel:${phone}`}>{phone}</a>; const phoneFormatter = phone => <a href={`tel:${phone}`}>{phone}</a>;

View File

@ -171,18 +171,13 @@ const ProductDetailsFooter = () => {
<StarCount stars={0} /> <StarCount stars={0} />
</FormGroup> </FormGroup>
<FormGroup> <FormGroup>
<FalconInput label="Name:" onChange={({ target }) => console.log(target.value)} /> <FalconInput label="Name:" onChange={value => console.log(value)} />
</FormGroup> </FormGroup>
<FormGroup> <FormGroup>
<FalconInput label="Email:" onChange={({ target }) => console.log(target.value)} type="email" /> <FalconInput label="Email:" onChange={value => console.log(value)} type="email" />
</FormGroup> </FormGroup>
<FormGroup> <FormGroup>
<FalconInput <FalconInput label="Review:" onChange={value => console.log(value)} type="textarea" rows="2" />
label="Review:"
onChange={({ target }) => console.log(target.value)}
type="textarea"
rows="2"
/>
</FormGroup> </FormGroup>
<Button color="primary" type="submit"> <Button color="primary" type="submit">
Submit Submit

View File

@ -1,4 +1,4 @@
import React, { useContext, useState } from 'react'; import React, { useContext } from 'react';
import { Collapse, Navbar, NavItem, Nav } from 'reactstrap'; import { Collapse, Navbar, NavItem, Nav } from 'reactstrap';
import classNames from 'classnames'; import classNames from 'classnames';
import AppContext from '../../context/Context'; import AppContext from '../../context/Context';
@ -9,26 +9,34 @@ import NavbarTopDropDownMenus from './NavbarTopDropDownMenus';
import { navbarBreakPoint, topNavbarBreakpoint } from '../../config'; import { navbarBreakPoint, topNavbarBreakpoint } from '../../config';
const NavbarTop = () => { const NavbarTop = () => {
const { showBurgerMenu, setShowBurgerMenu, isTopNav } = useContext(AppContext); const {
const [navbarCollapsed, setNavbarCollapsed] = useState(false); showBurgerMenu,
setShowBurgerMenu,
isTopNav,
isVertical,
isCombo,
navbarCollapsed,
setNavbarCollapsed
} = useContext(AppContext);
const handleBurgerMenu = () => {
isTopNav && !isCombo && setNavbarCollapsed(!navbarCollapsed);
(isCombo || isVertical) && setShowBurgerMenu(!showBurgerMenu);
};
return ( return (
<Navbar <Navbar
light light
className="navbar-glass fs--1 font-weight-semi-bold row navbar-top sticky-kit" className="navbar-glass fs--1 font-weight-semi-bold row navbar-top sticky-kit"
expand={isTopNav ? topNavbarBreakpoint : navbarBreakPoint} expand={topNavbarBreakpoint}
> >
<div <div
className={classNames('toggle-icon-wrapper mr-md-3 mr-2', { className={classNames('toggle-icon-wrapper mr-md-3 mr-2', {
'd-lg-none': isTopNav, 'd-lg-none': isTopNav && !isCombo,
[`d-${navbarBreakPoint}-none`]: !isTopNav [`d-${navbarBreakPoint}-none`]: isVertical || isCombo
})} })}
> >
<button <button
className="navbar-toggler-humburger-icon btn btn-link d-flex align-item-center justify-content-center " className="navbar-toggler-humburger-icon btn btn-link d-flex flex-center"
onClick={() => { onClick={handleBurgerMenu}
!isTopNav ? setShowBurgerMenu(!showBurgerMenu) : setNavbarCollapsed(!navbarCollapsed);
}}
id="burgerMenu" id="burgerMenu"
> >
<span className="navbar-toggle-icon"> <span className="navbar-toggle-icon">

View File

@ -9,14 +9,22 @@ import ToggleButton from './ToggleButton';
import AppContext from '../../context/Context'; import AppContext from '../../context/Context';
import Flex from '../common/Flex'; import Flex from '../common/Flex';
import routes from '../../routes'; import routes from '../../routes';
import { navbarBreakPoint } from '../../config'; import { navbarBreakPoint, topNavbarBreakpoint } from '../../config';
import bgNavbarImg from '../../assets/img/generic/bg-navbar.png'; import bgNavbarImg from '../../assets/img/generic/bg-navbar.png';
import NavbarTopDropDownMenus from './NavbarTopDropDownMenus';
const NavbarVertical = ({ navbarStyle }) => { const NavbarVertical = ({ navbarStyle }) => {
const navBarRef = useRef(null); const navBarRef = useRef(null);
const { showBurgerMenu, isNavbarVerticalCollapsed, setIsNavbarVerticalCollapsed } = useContext(AppContext); const {
showBurgerMenu,
isNavbarVerticalCollapsed,
setIsNavbarVerticalCollapsed,
isCombo,
setShowBurgerMenu,
setNavbarCollapsed
} = useContext(AppContext);
const HTMLClassList = document.getElementsByTagName('html')[0].classList; const HTMLClassList = document.getElementsByTagName('html')[0].classList;
//Control Component did mount and unmounted of hover effect //Control Component did mount and unmounted of hover effect
@ -48,7 +56,6 @@ const NavbarVertical = ({ navbarStyle }) => {
}, 100); }, 100);
} }
}; };
return ( return (
<Navbar <Navbar
expand={navbarBreakPoint} expand={navbarBreakPoint}
@ -85,10 +92,19 @@ const NavbarVertical = ({ navbarStyle }) => {
<NavbarVerticalMenu routes={routes} /> <NavbarVerticalMenu routes={routes} />
</Nav> </Nav>
<div className="settings px-3 px-xl-0"> <div className="settings px-3 px-xl-0">
{isCombo && (
<div className={`d-${topNavbarBreakpoint}-none`}>
<div className="navbar-vertical-divider">
<hr className="navbar-vertical-hr my-2" />
</div>
<Nav navbar>
<NavbarTopDropDownMenus setNavbarCollapsed={setNavbarCollapsed} setShowBurgerMenu={setShowBurgerMenu} />
</Nav>
</div>
)}
<div className="navbar-vertical-divider"> <div className="navbar-vertical-divider">
<hr className="navbar-vertical-hr my-2" /> <hr className="navbar-vertical-hr my-2" />
</div> </div>
<Button <Button
tag={'a'} tag={'a'}
href="https://myems.io" href="https://myems.io"
@ -101,8 +117,6 @@ const NavbarVertical = ({ navbarStyle }) => {
Purchase Purchase
</Button> </Button>
</div> </div>
{/* </Scrollbar> */}
</Collapse> </Collapse>
</Navbar> </Navbar>
); );

View File

@ -1,13 +1,11 @@
import React, { useContext } from 'react'; import React, { useContext } from 'react';
import AppContext from '../../context/Context'; import AppContext from '../../context/Context';
import { Link } from 'react-router-dom';
const SettingsAnimatedIcon = () => { const SettingsAnimatedIcon = () => {
const { toggleModal } = useContext(AppContext); const { toggleModal } = useContext(AppContext);
return ( return (
<Link <div
className="settings-popover nav-link" className="settings-popover nav-link cursor-pointer"
to="#!"
onClick={() => { onClick={() => {
toggleModal(); toggleModal();
}} }}
@ -23,7 +21,7 @@ const SettingsAnimatedIcon = () => {
</svg> </svg>
</span> </span>
</span> </span>
</Link> </div>
); );
}; };

View File

@ -15,7 +15,17 @@ const TopNavRightSideNavItem = () => {
<NavItem> <NavItem>
<SettingsAnimatedIcon /> <SettingsAnimatedIcon />
</NavItem> </NavItem>
{isTopNav && (
<NavItem className={`p-2 px-lg-0 cursor-pointer d-none d-sm-block`}>
<NavLink tag={Link} to="/changelog" id="changelog">
<FontAwesomeIcon icon="code-branch" transform="right-6 grow-4" />
</NavLink>
<UncontrolledTooltip autohide={false} placement="left" target="changelog">
Changelog
</UncontrolledTooltip>
</NavItem>
)}
<CartNotification />
<NotificationDropdown /> <NotificationDropdown />
<ProfileDropdown /> <ProfileDropdown />
</Nav> </Nav>

View File

@ -4,6 +4,7 @@ import { Button, Card, CardBody } from 'reactstrap';
import PageHeader from '../common/PageHeader'; import PageHeader from '../common/PageHeader';
import FalconEditor from '../common/FalconEditor'; import FalconEditor from '../common/FalconEditor';
import FalconCardHeader from '../common/FalconCardHeader'; import FalconCardHeader from '../common/FalconCardHeader';
import CodeHighlight from '../common/CodeHighlight';
const FontAwesome = () => ( const FontAwesome = () => (
<Fragment> <Fragment>
@ -24,11 +25,44 @@ const FontAwesome = () => (
<FontAwesomeIcon icon="chevron-right" className="ml-1 fs--2" /> <FontAwesomeIcon icon="chevron-right" className="ml-1 fs--2" />
</Button> </Button>
</PageHeader> </PageHeader>
<Card> <Card className="mb-3">
<FalconCardHeader title="Example" /> <FalconCardHeader title="Add Icon" />
<CardBody> <CardBody>
<p>
For adding new icon, go to <code>src/helpers/initFA.js</code> file. We initialize all fontawesome icons here.
Import your icon from your desired icon module and then pass it to <code>library.add()</code> function.
</p>
<CodeHighlight
code={`import { library } from '@fortawesome/fontawesome-svg-core'
import { faGulp } from '@fortawesome/free-brands-svg-icons' // module
import { faCheckSquare, faHome } from '@fortawesome/free-solid-svg-icons' // module
library.add(faGulp, faCheckSquare, faHome)`}
language="jsx"
/>
<p className="mb-0 mt-3">
For better understanding you can visit{' '}
<a href="https://www.npmjs.com/package/@fortawesome/react-fontawesome#usage">fontawesome usage</a>
</p>
</CardBody>
</Card>
<Card>
<FalconCardHeader title="Basic Usage" />
<CardBody>
<p>
Now in your component file just import the <code>FontAwesomeIcon</code> component, and when you use it, supply
the icon prop an icon name as a string
</p>
<CodeHighlight code={`import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';`} language="jsx" />
<br />
<FalconEditor <FalconEditor
code={`<FontAwesomeIcon icon="user" transform="grow-12 right-6" className="text-success" />`} code={`<FontAwesomeIcon icon="home" className="text-success fs-2" />`}
scope={{ FontAwesomeIcon }}
language="jsx"
/>
<br />
<FalconEditor
code={`<FontAwesomeIcon icon={['fab', 'gulp']} className="text-danger fs-4" />`}
scope={{ FontAwesomeIcon }} scope={{ FontAwesomeIcon }}
language="jsx" language="jsx"
/> />

View File

@ -45,7 +45,7 @@ const leafletCode = `function LeafletMap () {
: ['bright:101%', 'contrast:101%', 'hue:23deg', 'saturate:225%']; : ['bright:101%', 'contrast:101%', 'hue:23deg', 'saturate:225%'];
if(mapWidht){ if(mapWidth){
useEffect(() => { useEffect(() => {
L.tileLayer L.tileLayer
.colorFilter('https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}{r}.png', { .colorFilter('https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}{r}.png', {
@ -63,7 +63,7 @@ const leafletCode = `function LeafletMap () {
maxZoom={18} maxZoom={18}
zoomSnap={0.5} zoomSnap={0.5}
className="h-100 w-100" className="h-100 w-100"
style={{ width:mapWidht, minHeight: 300 }} style={{ width:mapWidth, minHeight: 300 }}
ref={map} ref={map}
> >
<MarkerCluster markers={markers} /> <MarkerCluster markers={markers} />
@ -75,17 +75,17 @@ const leafletCode = `function LeafletMap () {
const Leaflet = () => { const Leaflet = () => {
const { isDark } = useContext(AppContext); const { isDark } = useContext(AppContext);
let map = useRef(null); let map = useRef(null);
const [mapWidht, setMapwidth] = useState(); const [mapWidth, setMapWidth] = useState();
const egMap = useRef(); const egMap = useRef();
useEffect(() => { useEffect(() => {
const timer = setTimeout(() => { const timer = setTimeout(() => {
setMapwidth(egMap.current.offsetWidth); setMapWidth(egMap.current.offsetWidth);
}, 500); }, 500);
return () => { return () => {
clearTimeout(timer); clearTimeout(timer);
}; };
}, [isDark, mapWidht]); }, [isDark, mapWidth]);
return ( return (
<Fragment> <Fragment>
@ -107,7 +107,7 @@ const Leaflet = () => {
<CardBody className="p-0"> <CardBody className="p-0">
<FalconEditor <FalconEditor
code={leafletCode} code={leafletCode}
scope={{ AppContext, MarkerCluster, Map, map, mapWidht, L }} scope={{ AppContext, MarkerCluster, Map, map, mapWidth, L }}
language="jsx" language="jsx"
/> />
</CardBody> </CardBody>

View File

@ -24,6 +24,7 @@ import { withTranslation } from 'react-i18next';
const SidePanelModal = ({ autoShow, showOnce, autoShowDelay, cookieExpireTime, path, t }) => { const SidePanelModal = ({ autoShow, showOnce, autoShowDelay, cookieExpireTime, path, t }) => {
const { const {
isCombo,
isOpenSidePanel, isOpenSidePanel,
toggleModal, toggleModal,
isFluid, isFluid,
@ -34,9 +35,11 @@ const SidePanelModal = ({ autoShow, showOnce, autoShowDelay, cookieExpireTime, p
setIsDark, setIsDark,
isTopNav, isTopNav,
setIsTopNav, setIsTopNav,
setIsOpenSidePanel setIsOpenSidePanel,
setIsCombo,
isVertical,
setIsVertical
} = useContext(AppContext); } = useContext(AppContext);
const isKanban = getPageName('kanban'); const isKanban = getPageName('kanban');
useEffect(() => { useEffect(() => {
@ -49,7 +52,6 @@ const SidePanelModal = ({ autoShow, showOnce, autoShowDelay, cookieExpireTime, p
}, autoShowDelay); }, autoShowDelay);
} }
}, [autoShow, showOnce, setIsOpenSidePanel, autoShowDelay, cookieExpireTime]); }, [autoShow, showOnce, setIsOpenSidePanel, autoShowDelay, cookieExpireTime]);
return ( return (
<Modal <Modal
isOpen={isOpenSidePanel} isOpen={isOpenSidePanel}
@ -157,28 +159,46 @@ const SidePanelModal = ({ autoShow, showOnce, autoShowDelay, cookieExpireTime, p
<CustomInput <CustomInput
type="radio" type="radio"
id="verticalNav-radio" id="verticalNav-radio"
label={t('Vertical Nav')} label="Vertical"
checked={!isTopNav} name="NavBarPositionRadioButton"
onChange={({ target }) => setIsTopNav(!target.checked)} checked={!isCombo && isVertical}
onChange={({ target }) => {
setIsVertical(target.checked);
setIsTopNav(!target.checked);
setIsCombo(!target.checked);
}}
inline inline
/> />
<CustomInput <CustomInput
type="radio" type="radio"
id="topNav-radio" id="topNav-radio"
label={t('Top Nav')} label="Top"
checked={isTopNav} name="NavBarPositionRadioButton"
onChange={({ target }) => setIsTopNav(target.checked)} checked={!isCombo && isTopNav}
onChange={({ target }) => {
setIsTopNav(target.checked);
setIsVertical(!target.checked);
setIsCombo(!target.checked);
}}
inline
/>
<CustomInput
type="radio"
id="combo-radio"
label="Combo"
name="NavBarPositionRadioButton"
checked={isCombo}
onChange={({ target }) => {
setIsCombo(target.checked);
setIsTopNav(target.checked);
setIsVertical(target.checked);
}}
inline inline
/> />
</Media> </Media>
</Media> </Media>
<hr /> <hr />
<h5 className="fs-0 d-flex align-items-center"> <h5 className="fs-0 d-flex align-items-center">{t('Vertical Navbar Style')}</h5>
{t('Vertical Navbar Style')}{' '}
<Badge pill color="soft-success" className="fs--2 ml-2">
new
</Badge>
</h5>
<p className="fs--1">{t('Switch between styles for your vertical navbar')}</p> <p className="fs--1">{t('Switch between styles for your vertical navbar')}</p>
<div className="btn-group-toggle btn-block btn-group-navbar-style"> <div className="btn-group-toggle btn-block btn-group-navbar-style">
<ButtonGroup className="btn-block"> <ButtonGroup className="btn-block">

View File

@ -3,3 +3,19 @@ export const navbarBreakPoint = 'xl'; // Vertical navbar breakpoint
export const topNavbarBreakpoint = 'lg'; export const topNavbarBreakpoint = 'lg';
//export const APIBaseURL = 'http://127.0.0.1:8000'; //export const APIBaseURL = 'http://127.0.0.1:8000';
export const APIBaseURL = window.location.protocol+"//"+window.location.hostname+":"+window.location.port+"/api"; 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 };

View File

@ -1,15 +1,7 @@
import { createContext } from 'react'; import { createContext } from 'react';
import { settings } from '../config';
const AppContext = createContext({ const AppContext = createContext(settings);
isFluid: true,
isRTL: false,
isDark: true,
showBurgerMenu: false, // controls showing vertical nav on mobile
currency: '$',
isNavbarVerticalCollapsed: false,
navbarStyle: 'vibrant',
language: 'zh_cn',
});
export const EmailContext = createContext({ emails: [] }); export const EmailContext = createContext({ emails: [] });

View File

@ -17,7 +17,7 @@ import { getPageName } from '../helpers/utils';
const DashboardRoutes = loadable(() => import('./MyEMSRoutes')); const DashboardRoutes = loadable(() => import('./MyEMSRoutes'));
const DashboardLayout = ({ location }) => { const DashboardLayout = ({ location }) => {
const { isFluid, isTopNav, navbarStyle } = useContext(AppContext); const { isFluid, isVertical, navbarStyle } = useContext(AppContext);
const isKanban = getPageName('kanban'); const isKanban = getPageName('kanban');
@ -31,7 +31,7 @@ const DashboardLayout = ({ location }) => {
return ( return (
<div className={isFluid || isKanban ? 'container-fluid' : 'container'}> <div className={isFluid || isKanban ? 'container-fluid' : 'container'}>
{!isTopNav && <NavbarVertical isKanban={isKanban} navbarStyle={navbarStyle} />} {isVertical && <NavbarVertical isKanban={isKanban} navbarStyle={navbarStyle} />}
<ProductProvider> <ProductProvider>
<div className="content"> <div className="content">
<NavbarTop /> <NavbarTop />

View File

@ -42,6 +42,7 @@ import ProgressBar from '../components/bootstrap-components/ProgressBar';
import Tables from '../components/bootstrap-components/Tables'; import Tables from '../components/bootstrap-components/Tables';
import Tooltips from '../components/bootstrap-components/Tooltips'; import Tooltips from '../components/bootstrap-components/Tooltips';
import NavBarTop from '../components/bootstrap-components/NavBarTop'; import NavBarTop from '../components/bootstrap-components/NavBarTop';
import Combo from '../components/bootstrap-components/Combo';
import VerticalNavbar from '../components/bootstrap-components/VerticalNavbar'; import VerticalNavbar from '../components/bootstrap-components/VerticalNavbar';
import Sidepanel from '../components/bootstrap-components/Sidepanel'; import Sidepanel from '../components/bootstrap-components/Sidepanel';
import CookieNotice from '../components/bootstrap-components/CookieNotice'; import CookieNotice from '../components/bootstrap-components/CookieNotice';
@ -191,6 +192,7 @@ const DashboardRoutes = () => (
<Route path="/components/navs" exact component={Navs} /> <Route path="/components/navs" exact component={Navs} />
<Route path="/components/navbars" exact component={Navbars} /> <Route path="/components/navbars" exact component={Navbars} />
<Route path="/components/navbar-top" exact component={NavBarTop} /> <Route path="/components/navbar-top" exact component={NavBarTop} />
<Route path="/components/combo" exact component={Combo} />
<Route path="/components/navbar-vertical" exact component={VerticalNavbar} /> <Route path="/components/navbar-vertical" exact component={VerticalNavbar} />
<Route path="/components/Sidepanel" exact component={Sidepanel} /> <Route path="/components/Sidepanel" exact component={Sidepanel} />
<Route path="/components/pageheaders" exact component={PageHeaders} /> <Route path="/components/pageheaders" exact component={PageHeaders} />
@ -229,7 +231,7 @@ const DashboardRoutes = () => (
<Route path="/plugins/chart" exact component={Chart} /> <Route path="/plugins/chart" exact component={Chart} />
<Route path="/plugins/countup" exact component={CountUpExample} /> <Route path="/plugins/countup" exact component={CountUpExample} />
<Route path="/plugins/datetime" exact component={DatetimeExample} /> <Route path="/plugins/datetime" exact component={DatetimeExample} />
<Route path="/plugins/fontawesome" exact component={FontAwesome} /> <Route path="/plugins/font-awesome" exact component={FontAwesome} />
<Route path="/plugins/echarts" exact component={Echarts} /> <Route path="/plugins/echarts" exact component={Echarts} />
<Route path="/plugins/toastify" exact component={Toastify} /> <Route path="/plugins/toastify" exact component={Toastify} />
<Route path="/plugins/select" exact component={Select} /> <Route path="/plugins/select" exact component={Select} />

View File

@ -26,11 +26,11 @@ const Layout = () => {
<Router fallback={<span />}> <Router fallback={<span />}>
<Switch> <Switch>
<Route path="/landing" exact component={Landing} /> <Route path="/landing" exact component={Landing} />
<Route path="/authentication/basic" component={AuthBasicLayout} />
<Route path="/authentication/card" component={AuthCardRoutes} /> <Route path="/authentication/card" component={AuthCardRoutes} />
<Route path="/authentication/split" component={AuthSplitRoutes} /> <Route path="/authentication/split" component={AuthSplitRoutes} />
<Route path="/authentication/wizard" component={WizardLayout} /> <Route path="/authentication/wizard" component={WizardLayout} />
<Route path="/errors" component={ErrorLayout} /> <Route path="/errors" component={ErrorLayout} />
<Route path="/authentication/basic" component={AuthBasicLayout} />
<Route component={DashboardLayout} /> <Route component={DashboardLayout} />
</Switch> </Switch>
<ToastContainer transition={Fade} closeButton={<CloseButton />} position={toast.POSITION.BOTTOM_LEFT} /> <ToastContainer transition={Fade} closeButton={<CloseButton />} position={toast.POSITION.BOTTOM_LEFT} />