django-bananas
Version:
React admin frontend for Django.
273 lines (271 loc) • 10.3 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _material = require("@mui/material");
var _styles = require("@mui/styles");
var _classnames = _interopRequireDefault(require("classnames"));
var _propTypes = _interopRequireDefault(require("prop-types"));
var _react = _interopRequireDefault(require("react"));
var _AdminContext = _interopRequireDefault(require("./AdminContext"));
var _MenuItem = _interopRequireDefault(require("./MenuItem"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : String(i); }
function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
var hasSelectedChild = function hasSelectedChild(url) {
var children = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
return Boolean(children.filter(child => url.includes(child.path)).length);
};
var useStyles = (0, _styles.makeStyles)(theme => (0, _styles.createStyles)({
root: {
"&$verticalRoot > $list + $list": {
borderTopWidth: 1,
borderTopStyle: "solid",
borderTopColor: theme.palette.action.selected
},
"&$horizontalRoot": {
width: "100%",
height: "100%",
display: "flex",
flexDirection: "row",
justifyContent: "flex-start",
alignItems: "center",
"& $list:first-child": {
marginLeft: "auto"
},
"& $list:last-child": {
marginRight: "auto"
}
}
},
nestedMenuList: {
background: theme.palette.action.hover,
paddingTop: 0,
paddingBottom: 0,
"& > *": {
paddingLeft: "".concat(theme.gap(2), " !important")
},
"&$dense > *": {
paddingLeft: "0 !important"
}
},
verticalRoot: {},
horizontalRoot: {},
// List
list: {
"&:first-child": {
paddingTop: 0
},
"&:last-child": {
paddingBottom: 0
}
},
horizontal: {
display: "flex",
flexDirection: "row"
},
vertical: {
"&multiple": {
paddingTop: theme.gap(1),
paddingBottom: theme.gap(1)
}
},
dense: {},
multiple: {},
// Subheader
subheader: {
backgroundColor: theme.palette.background.paper,
textTransform: "uppercase",
fontSize: "".concat(0.75, "rem"),
overflow: "hidden",
height: theme.gap(4),
display: "flex",
alignItems: "center"
},
subheaderCollapsed: {
height: 0,
transition: theme.transitions.create("height", {
easing: theme.transitions.easing.sharp,
duration: theme.transitions.duration.leavingScreen
})
},
subheaderExpanded: {
transition: theme.transitions.create("height", {
easing: theme.transitions.easing.sharp,
duration: theme.transitions.duration.enteringScreen
})
}
}));
var transformRoutes = (routes, navProps) => {
var navKeys = Object.keys(navProps);
return routes.reduce((aggr, route) => {
if (navKeys.includes(route.id)) {
var np = navProps[route.id];
// differentiate between the value being an Object or an react component
if (np && typeof np === "function" || np && np.$$typeof) {
// {"example:user:list": {icon: IconComponent, parent: "Home"}}
return [...aggr, _objectSpread(_objectSpread({}, route), {}, {
icon: np
})];
}
// {"example:user:list": Icon}
return [...aggr, _objectSpread(_objectSpread({}, route), np)];
}
return [...aggr, route];
}, []);
};
var nestRoutes = passedRoutes => {
// separate parents and children
var splitRoutes = passedRoutes.reduce((_ref, r) => {
var {
parents,
children
} = _ref;
return r.parent ? {
children: [...children, r],
parents
} : {
parents: [...parents, r],
children
};
}, {
children: [],
parents: []
});
// if there are children, nest them ...
if (splitRoutes.children) {
return splitRoutes.parents.reduce((aggr, pa) => {
// find corresponding parent
// TODO : Handle orphans and deeper nesting of menu
var p = splitRoutes.children.filter(c => c.parent === pa.name);
return [...aggr, _objectSpread(_objectSpread({}, pa), {}, {
children: p
})];
}, []);
}
// ... and if not, return the parents. which means all of the routes.
return splitRoutes.parents;
};
function Navigation(props) {
var {
router
} = _react.default.useContext(_AdminContext.default);
var classes = useStyles();
var currentUrl = router.history.location.pathname;
var {
routes,
collapsed,
horizontal,
dense,
nav,
showIcons
} = props;
var navKeys = Object.keys(nav);
// Put items listed in `nav` first, then keep the original (alphabetical) order.
var indexMap = routes.reduce((result, route, index) => {
var navIndex = navKeys.indexOf(route.id);
result[route.id] = navIndex >= 0 ? navIndex : index + navKeys.length;
return result;
}, {});
var sortedRoutes = routes.slice().sort((a, b) => indexMap[a.id] - indexMap[b.id]);
var groupedRoutes = sortedRoutes.reduce((result, route) => {
var {
app
} = route;
var appRoutes = result[app];
if (appRoutes === undefined) {
appRoutes = [];
result[app] = appRoutes;
}
appRoutes.push(route);
return result;
}, {});
var apps = Object.keys(groupedRoutes);
var multipleApps = apps.length > 2;
var navigationItems = _react.default.useMemo(() => apps.map(app => {
var appRoutes = groupedRoutes[app];
// bypass nesting and just flatten the routes if the horizontal view is active
var appRoutesWithProps = transformRoutes(appRoutes, nav);
var appSettings = nav[app];
var nestedRoutes = horizontal ? appRoutesWithProps : nestRoutes(appRoutesWithProps);
var showSubheader = appSettings && appSettings.showSubheader !== undefined ? appSettings.showSubheader : true;
return /*#__PURE__*/_react.default.createElement(_material.List, {
key: app,
disablePadding: true,
className: (0, _classnames.default)(classes.list, {
[classes.horizontal]: horizontal,
[classes.vertical]: !horizontal,
[classes.dense]: horizontal && dense,
[classes.multiple]: multipleApps
}),
subheader: app && showSubheader && multipleApps && !horizontal && /*#__PURE__*/_react.default.createElement(_material.ListSubheader, {
className: (0, _classnames.default)(classes.subheader, {
[classes.subheaderCollapsed]: collapsed,
[classes.subheaderExpanded]: !collapsed
})
}, app)
}, nestedRoutes.map(_ref2 => {
var {
id,
path,
icon,
title,
children,
hidden
} = _ref2;
var variant = horizontal ? "appbar" : "drawer";
var isSelected = path.length > 1 ? Boolean(children !== undefined && hasSelectedChild(currentUrl, children)) || currentUrl.startsWith(path) : currentUrl === path;
return hidden !== true ? /*#__PURE__*/_react.default.createElement(_react.default.Fragment, {
key: id
}, (!horizontal && (showIcons || !showIcons && id !== "home") || horizontal && id !== "home") && /*#__PURE__*/_react.default.createElement(_MenuItem.default, {
route: id,
variant: variant,
title: title,
icon: showIcons ? icon : null,
dense: dense,
selected: isSelected,
collapsed: collapsed
}), Boolean(children && children.length) && /*#__PURE__*/_react.default.createElement(_material.Collapse, {
in: isSelected
}, /*#__PURE__*/_react.default.createElement(_material.MenuList, {
className: (0, _classnames.default)(classes.nestedMenuList, {
[classes.dense]: collapsed || dense
})
}, children.map(c => /*#__PURE__*/_react.default.createElement(_MenuItem.default, {
key: c.id,
route: c.id,
variant: variant,
title: c.title,
icon: showIcons ? c.icon : null,
dense: true,
selected: path.length > 1 ? currentUrl.includes(c.path) : currentUrl === path,
collapsed: collapsed
}))))) : null;
}));
}), [apps, classes.dense, classes.horizontal, classes.list, classes.multiple, classes.nestedMenuList, classes.subheader, classes.subheaderCollapsed, classes.subheaderExpanded, classes.vertical, collapsed, currentUrl, dense, groupedRoutes, horizontal, multipleApps, nav, showIcons]);
return /*#__PURE__*/_react.default.createElement("div", {
className: (0, _classnames.default)(classes.root, {
[classes.verticalRoot]: !horizontal,
[classes.horizontalRoot]: horizontal
})
}, navigationItems);
}
Navigation.propTypes = {
routes: _propTypes.default.array.isRequired,
collapsed: _propTypes.default.bool,
horizontal: _propTypes.default.bool,
dense: _propTypes.default.bool,
nav: _propTypes.default.object.isRequired,
showIcons: _propTypes.default.bool
};
Navigation.defaultProps = {
collapsed: false,
horizontal: false,
dense: true,
showIcons: false
};
var _default = exports.default = Navigation;