feat(roles): add admin store roles page, permission i18n, and menu integration
Some checks failed
Some checks failed
- Add admin store roles page with merchant→store cascading for superadmin and store-only selection for platform admin - Add permission catalog API with translated labels/descriptions (en/fr/de/lb) - Add permission translations to all 15 module locale files (60 files total) - Add info icon tooltips for permission descriptions in role editor - Add store roles menu item and admin menu item in module definition - Fix store-selector.js URL construction bug when apiEndpoint has query params - Add admin store roles API (CRUD + platform scoping) - Add integration tests for admin store roles and permission catalog Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -27,7 +27,7 @@ function storeRoles() {
|
||||
showRoleModal: false,
|
||||
editingRole: null,
|
||||
roleForm: { name: '', permissions: [] },
|
||||
permissionsByCategory: {},
|
||||
permissionCategories: [],
|
||||
presetRoles: ['manager', 'staff', 'support', 'viewer', 'marketing'],
|
||||
|
||||
async init() {
|
||||
@@ -50,40 +50,14 @@ function storeRoles() {
|
||||
|
||||
async loadPermissions() {
|
||||
try {
|
||||
// Group known permissions by category prefix
|
||||
const allPerms = window.USER_PERMISSIONS || [];
|
||||
this.permissionsByCategory = this.groupPermissions(allPerms);
|
||||
const response = await apiClient.get('/store/team/permissions/catalog');
|
||||
this.permissionCategories = response.categories || [];
|
||||
storeRolesLog.info('Loaded permission catalog:', this.permissionCategories.length, 'categories');
|
||||
} catch (e) {
|
||||
storeRolesLog.warn('Could not load permission categories:', e);
|
||||
storeRolesLog.warn('Could not load permission catalog:', e);
|
||||
}
|
||||
},
|
||||
|
||||
groupPermissions(permIds) {
|
||||
// Known permission categories from the codebase
|
||||
const knownPerms = [
|
||||
'dashboard.view',
|
||||
'settings.view', 'settings.edit', 'settings.theme', 'settings.domains',
|
||||
'products.view', 'products.create', 'products.edit', 'products.delete', 'products.import', 'products.export',
|
||||
'orders.view', 'orders.edit', 'orders.cancel', 'orders.refund',
|
||||
'customers.view', 'customers.edit', 'customers.delete', 'customers.export',
|
||||
'stock.view', 'stock.edit', 'stock.transfer',
|
||||
'team.view', 'team.invite', 'team.edit', 'team.remove',
|
||||
'analytics.view', 'analytics.export',
|
||||
'messaging.view_messages', 'messaging.send_messages', 'messaging.manage_templates',
|
||||
'billing.view_tiers', 'billing.manage_tiers', 'billing.view_subscriptions', 'billing.manage_subscriptions', 'billing.view_invoices',
|
||||
'cms.view_pages', 'cms.manage_pages', 'cms.view_media', 'cms.manage_media', 'cms.manage_themes',
|
||||
'loyalty.view_programs', 'loyalty.manage_programs', 'loyalty.view_rewards', 'loyalty.manage_rewards',
|
||||
'cart.view', 'cart.manage',
|
||||
];
|
||||
const groups = {};
|
||||
for (const perm of knownPerms) {
|
||||
const cat = perm.split('.')[0];
|
||||
if (!groups[cat]) groups[cat] = [];
|
||||
groups[cat].push({ id: perm });
|
||||
}
|
||||
return groups;
|
||||
},
|
||||
|
||||
async loadRoles() {
|
||||
this.loading = true;
|
||||
this.error = false;
|
||||
@@ -127,7 +101,7 @@ function storeRoles() {
|
||||
},
|
||||
|
||||
toggleCategory(category) {
|
||||
const perms = this.permissionsByCategory[category] || [];
|
||||
const perms = category.permissions || [];
|
||||
const permIds = perms.map(p => p.id);
|
||||
const allSelected = permIds.every(id => this.roleForm.permissions.includes(id));
|
||||
if (allSelected) {
|
||||
@@ -142,7 +116,7 @@ function storeRoles() {
|
||||
},
|
||||
|
||||
isCategoryFullySelected(category) {
|
||||
const perms = this.permissionsByCategory[category] || [];
|
||||
const perms = category.permissions || [];
|
||||
return perms.length > 0 && perms.every(p => this.roleForm.permissions.includes(p.id));
|
||||
},
|
||||
|
||||
|
||||
Reference in New Issue
Block a user