How can I hide the navigation bar between roles ('Admin' & 'user') in React js
Example
const [currentUser, setCurrentUser] = useState("");
const [role, setRole] = useState("");
let navigation = [];
useEffect(async () => {
// get user from Local storage
const user = authService.getCurrentUser();
if (!user) return;
setCurrentUser(user);
// get Role from Database
currentUser && setRole(authService.getRoleByUserId(currentUser.id));
console.log(currentUser);
}, [currentUser.id]);
if (currentUser && role === "Admin") {
navigation = [
{ name: "Home", href: "/Home", action: false, icon: false },
{ name: "Vendors", href: "/vendors", action: false, icon: false },
{ name: "Pricing", href: "/pricing", action: false, icon: false },
{ name: "Profile", href: "/profile", action: false, icon: false },
{ name: "Sign Out", href: "/", action: false, icon: false },
{ name: "", href: "/Cart", action: false, icon: true },
];
} else {
navigation = [
{ name: "Home", href: "/Home", action: false, icon: false },
{ name: "Pricing", href: "/pricing", action: false, icon: false },
{ name: "Sign In", href: "/login", action: false, icon: false },
{ name: "", href: "/Cart", action: false, icon: true },
];
}
return (
...
How can i do something this? Suggestions are always appreciated.
You shouldn't go with currentUser in your useEffect but with user.
Try:
// get user from Local storage
const user = authService.getCurrentUser();
if (!user) return;
setCurrentUser(user);
// get Role from Database
user && setRole(authService.getRoleByUserId(currentUser.id));
Related
Using Vue3 - Vuerouter4 - Vite
I try to import the components and routes in vue router but I face this error (only for the route that has children in my paths):
my router code:
import { createRouter, createWebHistory } from "vue-router";
import paths from "./path";
import { TokenService } from "#/services/storage.services.js";
function route(options) {
let path = options.path;
let view = options.view;
let name = options.name;
let meta = options.meta ? options.meta : "";
let children = options.children ? options.children : null;
let redirect = options.redirect ? options.redirect : null;
let currentRoute = {
name: name || view,
path,
meta,
component: (resolve) => import(`#/views/${view}.vue`).then(resolve),
};
if (children && Array.isArray(children)) {
children = children.map((path) => {
path.view = view + "/" + path.view;
return path;
});
currentRoute["children"] = children.map((path) => route(path));
}
if (redirect) {
currentRoute["redirect"] = redirect;
}
return currentRoute;
}
// Create a new router
const router = createRouter({
history: createWebHistory(),
routes: paths
.map((path) => route(path))
.concat([{ path: "/:pathMatch(.*)", redirect: "admin/home" }]),
scrollBehavior(to, from, savedPosition) {
if (savedPosition) {
return savedPosition;
}
if (to.hash) {
return { selector: to.hash };
}
return { left: 0, top: 0 };
},
});
export default router;
my paths that are in paths.js:
export default [
{
path: "/admin",
name: "Admin",
view: "Admin",
redirect: "Admin/Home",
children: [
{
path: "Home",
name: "Home",
view: "Home",
meta: {
auth: true,
title: "داشبورد",
},
},
{
path: "TRANSACTION",
name: "TRANSACTION",
view: "Transaction",
meta: {
auth: true,
title: "تراکنش ها",
},
},
{
path: "SMS-MANAGEMENT",
name: "SMSManagement",
view: "SMSManagement",
meta: {
auth: true,
title: "مدیریت پیامک ها",
},
},
{
path: "CAR-LIST",
name: "CAR-LIST",
view: "Car-List",
meta: {
auth: true,
title: "لیست خودرو های اجاره ای",
},
},
{
path: "ADDRENTCAR",
name: "ADDRENTCAR",
view: "AddRentCar",
meta: {
auth: false,
title: "افزودن خودرو اجاره ای",
},
},
{
path: "EDITRENTCAR",
name: "EDITRENTCAR",
view: "AddRentCar",
meta: {
auth: false,
title: "ویرایش خودرو اجاره ای",
},
},
{
path: "USERS",
name: "USERS",
view: "Users",
meta: {
auth: true,
title: "لیست کاربران",
},
},
{
path: "CARS",
name: "CARS",
view: "Cars",
meta: {
auth: true,
title: "لیست خودرو ها",
},
},
{
path: "REQUESTS",
name: "REQUESTS",
view: "REQUESTS",
meta: {
auth: true,
title: "لیست درخواست ها",
},
},
],
},
{
path: "",
name: "MAIN-HOME",
view: "main-home",
meta: {
auth: true,
title: "صفحه اصلی",
public: true,
},
},
{
path: "/PROFILE",
name: "PROFILE",
view: "PROFILE",
meta: {
auth: true,
title: "پروفایل من",
},
},
{
path: "/LOGIN",
name: "LOGIN",
view: "Login",
meta: {
auth: true,
title: "ورود",
},
},
{
path: "/ALLCARS",
name: "ALLCARS",
view: "ALLCARS",
meta: {
public: true,
auth: true,
title: "لیست تمام خودرو ها",
},
},
{
path: "/ABOUTUS",
name: "ABOUTUS",
view: "ABOUTUS",
meta: {
public: true,
auth: true,
title: "درباره ما",
},
},
];
Any ideas what causes the error specifically for my admin route that has children??!!
........................................................................................................................................................................................................................................................................................................................................................................................................................................................................
I changed the "../views/" to "/src/views/" and problem solved.
Seems like using '..' wouldn't make it to the src folder!!!!!
Thank you #Mohammad Masoudi
Hi I've implemented one simple shortcut to get data from input but after submitting the view I couldn't get the response payload or it cannot update the view to acknowledge user. following is my simple code.
const { App } = require("#slack/bolt");
const app = new App({
token: process.env.BOT_TOKEN,
socketMode: true,
signingSecret: process.env.SIGNIGN_SECRET,
appToken: process.env.APP_TOKEN,
});
app.shortcut({ callback_id: 'open_modal', type: 'message_action' }, async ({ shortcut, ack, client }) => {
try {
await ack();
console.log("Ack:")
const result = await client.views.open({
trigger_id: shortcut.trigger_id,
callback_id: "new-task-modal",
view: {
type: "modal",
title: {
type: "plain_text",
text: "My App",
},
submit: {
type: "plain_text",
text: "Submit",
emoji: true,
},
close: {
type: "plain_text",
text: "Cancel",
},
blocks: [
{
"type": "input",
"element": {
"type": "plain_text_input",
"action_id": "plain_text_input-action"
},
"label": {
"type": "plain_text",
"text": "Label",
"emoji": true
}
}
],
},
});
} catch (error) {
console.log(error);
}
});
app.view({ callback_id: 'new-task-modal', type: 'message_action' }, async({ shortcut, ack, view, body }) => {
try {
console.log("New task modal",view.state.values );
await ack();
let result = await client.views.update({
view_id: body.view.id,
view: {
type: "modal",
title: {
type: "plain_text",
text: "My App",
emoji: true,
},
close: {
type: "plain_text",
text: "Cancel",
},
blocks: [
{
type: "section",
text: {
type: "plain_text",
text: "This is a plain text section block.",
emoji: true,
},
},
],
}
});
} catch (error) {
console.log(error)
}
})
app.shortcut() function works fine and create one view but after submitting that view it couldn't hit to app.view() function to update the view so is there any way to update the current view.
The callback_id in the client.views.open call should be under the view field, not on the root level.
const result = await client.views.open({
trigger_id: shortcut.trigger_id,
- callback_id: "new-task-modal",
view: {
+ callback_id: "new-task-modal",
type: "modal",
title: {
type: "plain_text",
text: "My App",
},
...
I have one object and inside the object, there have roles(array of number) and I want to transform only the roles, it should be an array of objects. see below
current object,
displayConfiguration: {
widgetList: {
widgetName: 'widget tiltle',
entityType: 'Asset',
roles: [202]
},
addIcon: {
fileName: '',
fileDownloadUri: ''
},
displayInfoIcon: {
visible: true,
summaryText: 'info icon text'
},
useFilter: true
}
expected object
displayConfiguration: {
widgetList: {
widgetName: 'widget tiltle',
entityType: 'Asset',
roles: [
{
id: 202
}
]
},
addIcon: {
fileName: '',
fileDownloadUri: ''
},
displayInfoIcon: {
visible: true,
summaryText: 'info icon text'
},
useFilter: true
}
const displayConfiguration = {
widgetList: {
widgetName: 'widget tiltle',
entityType: 'Asset',
roles: [202]
},
addIcon: {
fileName: '',
fileDownloadUri: ''
},
displayInfoIcon: {
visible: true,
summaryText: 'info icon text'
},
useFilter: true
}
const answer = {
...displayConfiguration,
widgetList: {
...displayConfiguration.widgetList,
roles: displayConfiguration.widgetList.roles.map(x => ({id: x}))
}
}
console.log(answer)
Should be rather straight forward, you can use map function to transform array
You can you use .map() function, that will walk through each element and convert your number to object that you need.
const displayConfiguration = {
widgetList: {
widgetName: 'widget tiltle',
entityType: 'Asset',
roles: [202]
},
addIcon: {
fileName: '',
fileDownloadUri: ''
},
displayInfoIcon: {
visible: true,
summaryText: 'info icon text'
},
useFilter: true
};
const roles = displayConfiguration.widgetList.roles;
displayConfiguration.widgetList.roles = roles.map(role => {
return {
id: role
}
})
console.log(displayConfiguration);
The map function creates a new array populated with the results of calling a provided function on every element in the calling array.
As my project is growing, I've noticed a lot of repetitions. I'm starting with the navigations buttons, as they can appear in multiple places (side menu, navbar).
I'd like to centralize them and let the component import them as needed. So I've tried creating this file to hold all my menu items:
// menuItems.js
export default {
data() {
return {
items: [
{ title: 'Profile', icon: 'mdi-account-circle', reqAuth: true, hideOnAuth: false},
{ title: 'Dashboard', icon: 'mdi-view-dashboard', reqAuth: true, hideOnAuth: false },
{ title: 'Settings', icon: 'mdi-cog', reqAuth: true, hideOnAuth: false },
{ title: 'Signup', icon: 'mdi-account-circle-outline', reqAuth: false, hideOnAuth: true},
{ title: 'Login', icon: 'mdi-login', reqAuth: false, hideOnAuth: true },
{ title: 'Logout', icon: 'mdi-logout', reqAuth: true, hideOnAuth: false},
]
}
},
methods: {
menuItems: function(authenticated) {
if (!authenticated) {
// Gets items that do and don't require Auth, except for ones that should hide on Auth
return this.items.filter(o => o.reqAuth || !o.reqAuth && !o.hideOnAuth)
}
// Gets items that don't require Auth
return this.items.filter(o => !o.reqAuth)
}
}
}
Buttons can require authentication to be visible, and they can also be hidden once authenticated (eg. The login button).
Now lets assume I have a vue component for my nav bar, how do I import in the method that returns the filtered items?
// NavBarComponent.vue
<template>
<div>
<v-btn v-for="(item, i) in menuItems(authenticated)">
{{ item.title }}
</v-btn>
</div>
</template>
<script>
export default {
name: "NavBarComponent",
data() {
return {
authenticated: true,
}
},
methods: {
}
}
</script>
In this case, how do i make menuItems in the component reference the external file that will do the work of filtering?
You can create a mixin file and put your methods in that mixin and apply the mixin your component.
https://v2.vuejs.org/v2/guide/mixins.html
Your mixin would look like this:
// /mixins/menuItemsMixin.js
const menuItemsMixin= {
data() {
return {
items: [
{ title: 'Profile', icon: 'mdi-account-circle', reqAuth: true, hideOnAuth: false},
{ title: 'Dashboard', icon: 'mdi-view-dashboard', reqAuth: true, hideOnAuth: false },
{ title: 'Settings', icon: 'mdi-cog', reqAuth: true, hideOnAuth: false },
{ title: 'Signup', icon: 'mdi-account-circle-outline', reqAuth: false, hideOnAuth: true},
{ title: 'Login', icon: 'mdi-login', reqAuth: false, hideOnAuth: true },
{ title: 'Logout', icon: 'mdi-logout', reqAuth: true, hideOnAuth: false},
]
}
},
methods: {
menuItems: function(authenticated) {
if (!authenticated) {
// Gets items that do and don't require Auth, except for ones that should hide on Auth
return this.items.filter(o => o.reqAuth || !o.reqAuth && !o.hideOnAuth)
}
// Gets items that don't require Auth
return this.items.filter(o => !o.reqAuth)
}
}
};
export default menuItemsMixin
And in your component:
// NavBarComponent.vue
<script>
import menuItemsMixin from './mixins/menuItemsMixin.js'
export default {
mixins:[menuItemsMixin]
}
</script>
You can import this mixin in multiple components and you can also add more mixins in this component where the unique methods will be added.
I ended up creating a javascript file:
// views.js
export const views = [
{title: 'Dashboard'},
{title: 'Profile'},
{title: 'Login/Signup'},
]
then in my navbar component I imported it like so:
import {mapGetters} from "vuex";
import {views} from "../../common/views";
export default {
data: () => ({
items: views
}),
computed: {
...mapGetters(['isAuthenticated',])
menuItems: function (){
if (this.isAuthenticated) {
// do this
} else {
// do this
}
},
}
}
Then I did the same for the filtering function, but I could also just re-code it as needed if required in each component. I determined authentication state using Vuex's store, and retrieve it with mapgetters.
<componentA v-if='isAuthenticated'>
<navItem v-for='item in menuItems'>
</componentA>
i wanna product new menu i try Recursive dictionary array
but still not get correct datas.
below its two array , globalRoutes its dict array , menuRoutes its normal array i wanna use
menuRoutes to search globalRoutes
below its my code:
const globalRoutes = [
{
path: '/user',
meta: {
title: 'UserManager',
icon: 'el-icon-user'
},
children: [{
path: 'userinfo',
meta: {
title: 'UserInfo',
}
},
{
path: 'roleinfo',
meta: {
title: 'Roleinfo'
}
},
{
path: 'rolemenu',
meta: {
title: 'roleMenu'
}
}
]
},
{
path: '/test',
meta: {
title: 'TestMenu',
icon: 'el-icon-setting'
}
}
]
const menuRoutes = ['userinfo', '/test']
function Test1(routes) {
res = []
for(let route of routes){
console.log(route.path)
const data = {}
let menuIndex = menuRoutes.indexOf(route.path)
if(menuIndex > -1){
data.path = route.path
data.meta = route.meta
}else{
if(route.children){
data.path = route.path
data.meta = route.meta
data.children = Test1(route.children)
}
}
if (Object.keys(data).length > 0){
res.push(data)
}
}
return res
}
console.log(Test1(globalRoutes))
Error datas as below:
[
{ path: 'userinfo', meta: { title: 'UserInfo' } },
{
path: '/user',
meta: { title: 'UserManager', icon: 'el-icon-user' },
children: [Circular]
},
{
path: '/test',
meta: { title: 'TestMenu', icon: 'el-icon-setting' }
}
]
I wanted correct data as below:
[
{
path: '/user',
meta: { title: 'UserManager', icon: 'el-icon-user' },
children: [{ path: 'userinfo', meta: { title: 'UserInfo' } }]
},
{
path: '/test',
meta: { title: 'TestMenu', icon: 'el-icon-setting' }
}
]
how need i change code to get correct datas?
Here is simple example based on your code.
const globalRoutes = [
{
path: '/user',
meta: {
title: 'UserManager',
icon: 'el-icon-user'
},
children: [{
path: 'userinfo',
meta: {
title: 'UserInfo',
}
},
{
path: 'roleinfo',
meta: {
title: 'Roleinfo'
}
},
{
path: 'rolemenu',
meta: {
title: 'roleMenu'
}
}
]
},
{
path: '/test',
meta: {
title: 'TestMenu',
icon: 'el-icon-setting'
}
}
];
const menuRoutes = ['userinfo', '/test'];
const inRoutes = (search, routes) => {
let result = [];
routes.forEach((item, index) => {
if (search.includes(item.path)) {
result.push(item);
}
if (item.children) {
item.children.forEach((itm, idx) => {
if (search.includes(itm.path)) {
item.children = item.children.filter(i => i === itm); // or item.children = [itm];
result.push(item);
}
});
}
});
return result;
};
console.log(inRoutes(menuRoutes, globalRoutes));
Hope this helps.