Skip to content

Management Modules ​

Overview ​

The Management Modules system provides a comprehensive framework for organizing and managing different functional areas within the Admin Frontend application. Each module represents a distinct business domain with its own pages, components, permissions, and workflows.

Architecture ​

Module Structure ​

Each management module follows a consistent structure:

module-name/
├── pages/              # Module-specific pages
├── components/         # Module-specific components
├── store/             # Vuex store module
├── middleware/        # Route protection middleware
├── mixins/            # Module-specific mixins
└── utils/             # Module utilities

Core Modules ​

1. Digital Asset Management (DAM) Module ​

Purpose: Manage digital assets, folders, collages, and related operations.

Key Features:

  • Asset upload and management
  • Folder organization
  • Collage creation and management
  • Search and filtering
  • Sharing and permissions

Module Configuration:

javascript
{
  name: 'dam',
  displayName: 'Digital Asset Management',
  icon: 'FolderIcon', // Custom SVG icon component from @/components/svg
  route: '/:workspace_id/dam',
  enabled: true,
  permissions: {
    view: 'can-view-dam',
    create: 'can-create-assets',
    edit: 'can-edit-assets',
    delete: 'can-delete-assets',
    share: 'can-share-assets'
  },
  pages: [
    {
      path: 'dashboard',
      component: 'pages/_workspace_id/dam/dashboard/index.vue',
      middleware: ['authCheck', 'checkWorkspace', 'can-access-dam-module']
    },
    {
      path: 'folders',
      component: 'pages/_workspace_id/dam/folders/index.vue',
      middleware: ['authCheck', 'checkWorkspace', 'can-access-dam-module']
    },
    {
      path: 'collages',
      component: 'pages/_workspace_id/dam/collage/index.vue',
      middleware: ['authCheck', 'checkWorkspace', 'can-access-dam-module']
    }
  ]
}

Middleware: can-access-dam-module

Store Module: store/dam.js

2. Workspace Settings Module ​

Purpose: Manage workspace configuration, users, and settings.

Key Features:

  • User management
  • Workspace configuration
  • Subscription and billing
  • Module enablement

Module Configuration:

javascript
{
  name: 'workspace-settings',
  displayName: 'Workspace Settings',
  icon: 'SettingsIcon', // Custom SVG icon component from @/components/svg
  route: '/:workspace_id/workspace-settings',
  enabled: true,
  permissions: {
    view: 'can-view-settings',
    edit: 'can-edit-settings',
    manageUsers: 'can-manage-users'
  }
}

Module Registration ​

Frontend Registration ​

Modules are registered in the application configuration. Note: The application uses custom SVG icon components from @/components/svg instead of Material Design Icons (MDI). Icons should be imported as Vue components.

javascript
// plugins/modules.js
import FolderIcon from '@/components/svg/FolderIcon.vue'
import SettingsIcon from '@/components/svg/SettingsIcon.vue'

export default ({ app, store, router }) => {
  const modules = [
    {
      id: 'dam',
      name: 'Digital Asset Management',
      icon: 'FolderIcon', // Custom SVG icon component from @/components/svg
      route: '/:workspace_id/dam',
      enabled: true,
      permissions: ['can-access-dam-module']
    },
    {
      id: 'workspace-settings',
      name: 'Workspace Settings',
      icon: 'SettingsIcon', // Custom SVG icon component from @/components/svg
      route: '/:workspace_id/workspace-settings',
      enabled: true,
      permissions: ['can-view-settings']
    }
  ]

  // Register modules in store
  store.commit('modules/registerModules', modules)
}

Module Store ​

javascript
// store/modules.js
export const state = () => ({
  modules: [],
  activeModule: null,
  modulePermissions: {}
})

export const mutations = {
  registerModules(state, modules) {
    state.modules = modules
  },
  setActiveModule(state, module) {
    state.activeModule = module
  },
  setModulePermissions(state, { moduleId, permissions }) {
    state.modulePermissions[moduleId] = permissions
  }
}

export const getters = {
  enabledModules: (state) => {
    return state.modules.filter(m => m.enabled)
  },
  accessibleModules: (state, getters, rootState) => {
    const userPermissions = rootState.auth.user?.permissions || []
    return state.modules.filter(module => {
      if (!module.enabled) return false
      if (!module.permissions || module.permissions.length === 0) return true
      return module.permissions.some(perm => userPermissions.includes(perm))
    })
  },
  hasModuleAccess: (state) => (moduleId) => {
    const module = state.modules.find(m => m.id === moduleId)
    if (!module || !module.enabled) return false
    return true
  }
}

Module Navigation ​

vue
<template>
  <v-navigation-drawer v-model="drawer" app>
    <v-list>
      <v-list-item
        v-for="module in accessibleModules"
        :key="module.id"
        :to="getModuleRoute(module)"
        :disabled="!hasModuleAccess(module.id)"
      >
        <v-list-item-icon>
          <v-icon>{{ module.icon }}</v-icon>
        </v-list-item-icon>
        <v-list-item-content>
          <v-list-item-title>{{ module.name }}</v-list-item-title>
        </v-list-item-content>
      </v-list-item>
    </v-list>
  </v-navigation-drawer>
</template>

<script>
import { mapGetters } from 'vuex'

export default {
  computed: {
    ...mapGetters('modules', ['accessibleModules', 'hasModuleAccess']),
    drawer: {
      get() {
        return this.$store.state.ui.drawer
      },
      set(value) {
        this.$store.commit('ui/setDrawer', value)
      }
    }
  },
  methods: {
    getModuleRoute(module) {
      const workspaceId = this.$route.params.workspace_id
      return module.route.replace(':workspace_id', workspaceId)
    }
  }
}
</script>

Module Access Control ​

Middleware Implementation ​

javascript
// middleware/can-access-module.js
export default async function ({ route, store, redirect, $auth }) {
  const moduleId = route.meta?.moduleId
  if (!moduleId) return

  // Check if module exists and is enabled
  const hasAccess = store.getters['modules/hasModuleAccess'](moduleId)
  if (!hasAccess) {
    return redirect('/')
  }

  // Check user permissions
  const module = store.getters['modules/enabledModules'].find(m => m.id === moduleId)
  if (module && module.permissions) {
    const userPermissions = $auth.user?.permissions || []
    const hasPermission = module.permissions.some(perm => 
      userPermissions.includes(perm)
    )
    
    if (!hasPermission) {
      return redirect('/')
    }
  }
}

Page-Level Usage ​

javascript
// pages/_workspace_id/dam/dashboard/index.vue
export default {
  middleware: [
    'authCheck',
    'checkWorkspace',
    'can-access-dam-module'
  ],
  meta: {
    moduleId: 'dam'
  }
}

Module API ​

Backend Module Configuration ​

javascript
// API: GET /api/workspaces/:workspace_id/modules
{
  "modules": [
    {
      "id": "dam",
      "name": "Digital Asset Management",
      "enabled": true,
      "subscription_required": true,
      "permissions": {
        "view": "can-view-dam",
        "create": "can-create-assets",
        "edit": "can-edit-assets",
        "delete": "can-delete-assets"
      }
    },
  ]
}

Enable/Disable Module ​

javascript
// API: PUT /api/workspaces/:workspace_id/modules/:module_id
{
  "enabled": true
}

Workflow ​

Module Access Flow ​

1. User navigates to module route
   ↓
2. Middleware checks module access
   ↓
3. Verify module is enabled for workspace
   ↓
4. Check user has required permissions
   ↓
5. Load module-specific store
   ↓
6. Render module pages/components
   ↓
7. Apply module-specific middleware

Module Initialization Flow ​

1. Application starts
   ↓
2. Fetch workspace modules from API
   ↓
3. Register modules in Vuex store
   ↓
4. Filter modules by user permissions
   ↓
5. Build navigation menu
   ↓
6. Set active module on route change

Sample Data ​

Module Configuration Object ​

javascript
{
  id: "dam",
  name: "Digital Asset Management",
  displayName: "DAM",
  description: "Manage digital assets, folders, and collages",
  icon: "FolderIcon", // Custom SVG icon component from @/components/svg
  route: "/:workspace_id/dam",
  enabled: true,
  subscription_required: true,
  subscription_tier: "professional",
  permissions: [
    "can-access-dam-module",
    "can-view-dam",
    "can-create-assets",
    "can-edit-assets",
    "can-delete-assets",
    "can-share-assets"
  ],
  features: [
    "asset-upload",
    "folder-management",
    "collage-creation",
    "advanced-search",
    "sharing"
  ],
  limits: {
    max_assets: 10000,
    max_storage_gb: 100,
    max_users: 50
  },
  pages: [
    {
      path: "dashboard",
      name: "Dashboard",
      component: "Dashboard",
      middleware: ["authCheck", "can-access-dam-module"]
    },
    {
      path: "folders",
      name: "Folders",
      component: "Folders",
      middleware: ["authCheck", "can-access-dam-module"]
    }
  ]
}