diff --git a/client/src/components/MenuItem.js b/client/src/components/MenuItem.js
index 22fa80922..74144e45b 100644
--- a/client/src/components/MenuItem.js
+++ b/client/src/components/MenuItem.js
@@ -145,9 +145,10 @@ export default class MenuItem extends AbstractPureComponent2 {
tagName = "a",
dropdownType,
caretIconSize = 16,
+ hasSubmenu,
...htmlProps
} = this.props;
- const hasSubmenu = children != null;
+
const intentClass = Classes.intentClass(intent);
const anchorClasses = classNames(
diff --git a/client/src/components/Sidebar/SidebarMenu.js b/client/src/components/Sidebar/SidebarMenu.js
index 8b665903c..62164f715 100644
--- a/client/src/components/Sidebar/SidebarMenu.js
+++ b/client/src/components/Sidebar/SidebarMenu.js
@@ -8,6 +8,11 @@ import { MenuItemLabel } from 'components';
import classNames from 'classnames';
import SidebarOverlay from 'components/SidebarOverlay';
+const DEFAULT_ITEM = {
+ text: '',
+ href: '',
+}
+
export default function SidebarMenu() {
const history = useHistory();
const location = useLocation();
@@ -17,18 +22,16 @@ export default function SidebarMenu() {
const menuItemsMapper = (list) => {
return list.map((item, index) => {
- const children = Array.isArray(item.children)
- ? menuItemsMapper(item.children)
- : null;
+ const hasChildren = Array.isArray(item.children);
const matchPath = (pathname, path) => {
return item.matchExact
? pathname === path
: pathname.indexOf(path) !== -1;
};
- const isActive = item.children
+ const isActive = (item.children
? item.children.some((c) => matchPath(location.pathname, c.href))
- : item.href && matchPath(location.pathname, item.href);
+ : item.href && matchPath(location.pathname, item.href)) || currentItem ===item;
const handleItemClick = () => {
if (item.href) {
@@ -69,28 +72,34 @@ export default function SidebarMenu() {
text={item.text}
label={maybeRenderLabel(item)}
disabled={item.disabled}
- children={children}
dropdownType={item.dropdownType || 'collapse'}
caretIconSize={16}
onClick={handleItemClick}
callapseActive={!!isActive}
itemClassName={classNames({
'is-active': isActive,
- 'has-icon': !children && item.icon,
+ 'has-icon': !hasChildren && item.icon,
})}
+ hasSubmenu={hasChildren}
/>
);
});
};
const items = menuItemsMapper(sidebarMenuList);
+ const handleSidebarOverlayClose = () => {
+ setIsOpen(false);
+ }
+
return (
{' '}
);
diff --git a/client/src/components/SidebarOverlay/index.tsx b/client/src/components/SidebarOverlay/index.tsx
index e5759fc1c..200194f0c 100644
--- a/client/src/components/SidebarOverlay/index.tsx
+++ b/client/src/components/SidebarOverlay/index.tsx
@@ -2,24 +2,24 @@ import React from 'react';
import { Overlay } from '@blueprintjs/core';
import { Link } from 'react-router-dom';
import SidebarOverlayContainer from './SidebarOverlayContainer';
-
interface ISidebarOverlayItem {
text: string;
href: string;
divider?: boolean;
- label?: boolean
+ label?: boolean;
}
interface ISidebarOverlayProps {
isOpen: boolean;
items: ISidebarOverlayItem[];
- overlayProps: any;
- overlayContainerRef: any;
+ label: string;
+ onClose: Function;
}
interface ISidebarOverlayItemProps {
text: string;
href: string;
+ onLinkClick: Function;
}
interface ISidebarOverlayItemDivider {
@@ -28,16 +28,25 @@ interface ISidebarOverlayItemDivider {
/**
* Sidebar overlay item.
*/
-function SidebarOverlayItem({ text, href }: ISidebarOverlayItemProps) {
+function SidebarOverlayItem({
+ text,
+ href,
+ onLinkClick,
+}: ISidebarOverlayItemProps) {
+ const handleLinkClick = () => {
+ onLinkClick && onLinkClick();
+ };
return (
- {text}
+
+ {text}
+
);
}
interface ISidebarOverlayItemLabel {
- text: string;
+ text: string;
}
function SidebarOverlayLabel({ text }: ISidebarOverlayItemLabel) {
@@ -52,34 +61,75 @@ function SidebarOverlayDivider() {
* Sidebar overlay component.
*/
export default function SidebarOverlay({
- isOpen = false,
+ label,
+ isOpen: controllerdIsOpen,
+ onClose,
items,
}: ISidebarOverlayProps) {
- //
- if (!isOpen) {
+ const [isEverOpened, setEverOpened] = React.useState(false);
+ const [isOpen, setIsOpen] = React.useState(controllerdIsOpen);
+
+ React.useEffect(() => {
+ if (controllerdIsOpen && isOpen !== controllerdIsOpen) {
+ setIsOpen(controllerdIsOpen);
+ }
+ }, [controllerdIsOpen, setIsOpen, isOpen]);
+
+ React.useEffect(() => {
+ if (isOpen && !isEverOpened) {
+ setEverOpened(true);
+ }
+ }, [isEverOpened, isOpen]);
+
+ if (!isEverOpened) {
return '';
}
+ // Handle overlay close event.
const handleOverlayClose = () => {
-
+ setIsOpen(false);
+ onClose && onClose();
+ };
+ // Handle overlay open event.
+ const handleOverlayOpen = () => {
+ setIsOpen(true);
+ };
+ // Handle sidebar item link click.
+ const handleItemClick = () => {
+ setIsOpen(false);
+ onClose && onClose();
};
return (
-
+
+ {label && (
+ <>
+
+
+ >
+ )}
+
{items.map((item) =>
item.divider ? (
) : item.label ? (
) : (
-
+
),
)}
diff --git a/client/src/config/sidebarMenu.js b/client/src/config/sidebarMenu.js
index 02fa39ce6..725281380 100644
--- a/client/src/config/sidebarMenu.js
+++ b/client/src/config/sidebarMenu.js
@@ -27,6 +27,28 @@ export default [
text: ,
href: '/items/categories',
},
+ {
+ text: 'New tasks',
+ label: true,
+ },
+ {
+ divider: true,
+ },
+ {
+ text: ,
+ href: '/items/new',
+ },
+ {
+ text: ,
+ href: '/items/new',
+ },
+ {
+ text: ,
+ href: '/items/categories/new',
+ },
+ {
+ text: 'New inventory adjustment',
+ },
],
},
{
@@ -48,14 +70,34 @@ export default [
href: '/payment-receives',
newTabHref: '/payment-receives/new',
},
- {
- divider: true,
- },
{
text: ,
href: '/receipts',
newTabHref: '/receipts/new',
},
+ {
+ text: 'New tasks',
+ label: true,
+ },
+ {
+ divider: true,
+ },
+ {
+ text: ,
+ href: '/estimates/new',
+ },
+ {
+ text: ,
+ href: '/invoices/new',
+ },
+ {
+ text: ,
+ href: '/receipts/new',
+ },
+ {
+ text: ,
+ href: '/payment-receives/new',
+ },
],
},
{
@@ -71,6 +113,21 @@ export default [
href: '/payment-mades',
newTabHref: '/payment-mades/new',
},
+ {
+ text: 'New tasks',
+ label: true,
+ },
+ {
+ divider: true,
+ },
+ {
+ text: ,
+ href: '/bills/new',
+ },
+ {
+ text: ,
+ href: '/payment-mades/new',
+ },
],
},
{
@@ -86,6 +143,21 @@ export default [
href: '/vendors',
newTabHref: '/vendors/new',
},
+ {
+ text: 'New tasks',
+ label: true,
+ },
+ {
+ divider: true,
+ },
+ {
+ text: ,
+ href: '/customers/new',
+ },
+ {
+ text: ,
+ href: '/vendors/new',
+ },
],
},
{
@@ -103,14 +175,21 @@ export default [
text: ,
href: '/manual-journals',
},
- {
- text: ,
- href: '/make-journal-entry',
- },
{
text: ,
href: '/exchange-rates',
},
+ {
+ text: 'New tasks',
+ label: true,
+ },
+ {
+ divider: true,
+ },
+ {
+ text: ,
+ href: '/make-journal-entry',
+ },
],
},
{
@@ -133,15 +212,6 @@ export default [
{
text: ,
children: [
- {
- text: ,
- href: '/financial-reports',
- matchExact: true,
- label: true
- },
- {
- divider: true,
- },
{
text: ,
href: '/financial-reports/balance-sheet',
@@ -162,6 +232,10 @@ export default [
text: ,
href: '/financial-reports/profit-loss-sheet',
},
+ {
+ text: ,
+ href: '/financial-reports/cash-flow',
+ },
{
text: ,
href: '/financial-reports/receivable-aging-summary',
@@ -170,6 +244,52 @@ export default [
text: ,
href: '/financial-reports/payable-aging-summary',
},
+ {
+ text: ,
+ label: true,
+ },
+ {
+ divider: true,
+ },
+ {
+ text: ,
+ href: '/financial-reports/purchases-by-items',
+ },
+ {
+ text: ,
+ href: '/financial-reports/sales-by-items',
+ },
+ {
+ text: ,
+ href: '/financial-reports/transactions-by-customers',
+ },
+ {
+ text: ,
+ href: '/financial-reports/transactions-by-vendors',
+ },
+ {
+ text: ,
+ href: '/financial-reports/customers-balance-summary',
+ },
+ {
+ text: ,
+ href: '/financial-reports/vendors-balance-summary',
+ },
+ {
+ text: ,
+ label: true,
+ },
+ {
+ divider: true,
+ },
+ {
+ text: ,
+ href: '/financial-reports/inventory-item-details',
+ },
+ {
+ text: ,
+ href: '/financial-reports/inventory-valuation',
+ },
],
},
{
diff --git a/client/src/lang/en/index.json b/client/src/lang/en/index.json
index 384702549..6b2767ed4 100644
--- a/client/src/lang/en/index.json
+++ b/client/src/lang/en/index.json
@@ -1172,5 +1172,9 @@
"invoice_details":"Invoice details",
"receipt_details":"Receipt details",
"payment_receive_details":"Payment receive details",
- "payment_made_details":"Payment made details"
+ "payment_made_details":"Payment made details",
+ "New item category": "New item category",
+ "New service": "New service",
+ "New inventory item": "New inventory item",
+ "New purchase invoice": "New purchase invoice"
}
\ No newline at end of file
diff --git a/client/src/style/App.scss b/client/src/style/App.scss
index a014aa95d..187fd8ed9 100644
--- a/client/src/style/App.scss
+++ b/client/src/style/App.scss
@@ -204,7 +204,8 @@ html[lang^="ar"] {
.sidebar-overlay {
background: #fff;
height: 100%;
- width: 300px;
+ width: 240px;
+ outline: 0;
&__scroll-wrapper {
height: 100%
@@ -237,23 +238,23 @@ html[lang^="ar"] {
&.ScrollbarsCustom-ThumbX,
&.ScrollbarsCustom-ThumbY {
- background: rgba(255, 255, 255, 0.25);
+ background: rgba(0, 0, 0, 0.5);
}
}
}
&__menu {
- margin: 20px 0;
+ margin: 16px 0;
}
&__item {
font-size: 15px;
- color: #032259;
+ color: #001944;
a {
color: inherit;
display: block;
- padding: 9px 22px;
+ padding: 10px 22px;
text-decoration: none;
&:hover,
@@ -265,15 +266,56 @@ html[lang^="ar"] {
&__divider {
height: 1px;
- margin: 4px 0;
- background: #ebebeb;
+ margin: 6px 0;
+ background: #e2e5ec;
}
&__label{
text-transform: uppercase;
font-size: 12px;
- padding: 4px 20px;
- letter-spacing: 0.8px;
+ padding: 14px 20px 10px;
+ letter-spacing: 1px;
color: #707a85;
}
+
+ &__label + .sidebar-overlay__divider{
+ margin-top: 0;
+ }
+}
+
+.sidebar-overlay-transition {
+ transform: translateX(-100%);
+
+ &.bp3-overlay{
+ &-appear,
+ &-enter {
+ transform: translateX(-100%)
+ }
+
+ &-appear-active,
+ &-enter-active {
+ transform: translateX(0) !important;
+ transition: all 200ms ease-in-out;
+ }
+
+ &-appear-done,
+ &-enter-done {
+ transform: translateX(0) !important;
+ }
+
+ &-exit {
+ transform: translateX(0) !important;
+ }
+ &-exit-active {
+ transform: translateX(-100%) !important;
+ transition: all 200ms ease-in-out;
+ }
+ &-exit-done{
+ transform: translateX(-100%) !important;
+ }
+ }
+
+}
+.sidebar-overlay-backdrop{
+ background-color: rgba(0, 10, 30, 0.6);
}
\ No newline at end of file