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"]
    }
  ]
}