Add USB, Notifications, Network plugins and reusable EmployeeSearch component

New Plugins:
- USB plugin: Device checkout/checkin with employee lookup, checkout history
- Notifications plugin: Announcements with types, scheduling, shopfloor display
- Network plugin: Network device management with subnets and VLANs
- Equipment and Computers plugins: Asset type separation

Frontend:
- EmployeeSearch component: Reusable employee lookup with autocomplete
- USB views: List, detail, checkout/checkin modals
- Notifications views: List, form with recognition mode
- Network views: Device list, detail, form
- Calendar view with FullCalendar integration
- Shopfloor and TV dashboard views
- Reports index page
- Map editor for asset positioning
- Light/dark mode fixes for map tooltips

Backend:
- Employee search API with external lookup service
- Collector API for PowerShell data collection
- Reports API endpoints
- Slides API for TV dashboard
- Fixed AppVersion model (removed BaseModel inheritance)
- Added checkout_name column to usbcheckouts table

Styling:
- Unified detail page styles
- Improved pagination (page numbers instead of prev/next)
- Dark/light mode theme improvements

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
cproudlock
2026-01-21 16:37:49 -05:00
parent 7e729c8fdc
commit c8b325d2e7
108 changed files with 17693 additions and 600 deletions

View File

@@ -22,6 +22,16 @@ import KnowledgeBaseList from '../views/knowledgebase/KnowledgeBaseList.vue'
import KnowledgeBaseDetail from '../views/knowledgebase/KnowledgeBaseDetail.vue'
import KnowledgeBaseForm from '../views/knowledgebase/KnowledgeBaseForm.vue'
import SearchResults from '../views/SearchResults.vue'
import NotificationsList from '../views/notifications/NotificationsList.vue'
import NotificationForm from '../views/notifications/NotificationForm.vue'
import USBList from '../views/usb/USBList.vue'
import USBDetail from '../views/usb/USBDetail.vue'
import USBForm from '../views/usb/USBForm.vue'
import NetworkDevicesList from '../views/network/NetworkDevicesList.vue'
import NetworkDeviceDetail from '../views/network/NetworkDeviceDetail.vue'
import NetworkDeviceForm from '../views/network/NetworkDeviceForm.vue'
import ReportsIndex from '../views/reports/ReportsIndex.vue'
import CalendarView from '../views/CalendarView.vue'
import SettingsIndex from '../views/settings/SettingsIndex.vue'
import MachineTypesList from '../views/settings/MachineTypesList.vue'
import LocationsList from '../views/settings/LocationsList.vue'
@@ -30,7 +40,13 @@ import ModelsList from '../views/settings/ModelsList.vue'
import PCTypesList from '../views/settings/PCTypesList.vue'
import OperatingSystemsList from '../views/settings/OperatingSystemsList.vue'
import BusinessUnitsList from '../views/settings/BusinessUnitsList.vue'
import VLANsList from '../views/settings/VLANsList.vue'
import SubnetsList from '../views/settings/SubnetsList.vue'
import MapView from '../views/MapView.vue'
import MapEditor from '../views/MapEditor.vue'
import ShopfloorDashboard from '../views/ShopfloorDashboard.vue'
import TVDashboard from '../views/TVDashboard.vue'
import EmployeeDetail from '../views/employees/EmployeeDetail.vue'
const routes = [
{
@@ -39,6 +55,17 @@ const routes = [
component: Login,
meta: { guest: true }
},
// Standalone full-screen dashboards (no sidebar, no auth required)
{
path: '/shopfloor',
name: 'shopfloor',
component: ShopfloorDashboard
},
{
path: '/tv',
name: 'tv',
component: TVDashboard
},
{
path: '/',
component: AppLayout,
@@ -124,6 +151,12 @@ const routes = [
name: 'map',
component: MapView
},
{
path: 'map/editor',
name: 'map-editor',
component: MapEditor,
meta: { requiresAuth: true }
},
{
path: 'applications',
name: 'applications',
@@ -168,6 +201,82 @@ const routes = [
component: KnowledgeBaseForm,
meta: { requiresAuth: true }
},
{
path: 'notifications',
name: 'notifications',
component: NotificationsList
},
{
path: 'notifications/new',
name: 'notification-new',
component: NotificationForm,
meta: { requiresAuth: true }
},
{
path: 'notifications/:id',
name: 'notification-detail',
component: NotificationForm
},
{
path: 'notifications/:id/edit',
name: 'notification-edit',
component: NotificationForm,
meta: { requiresAuth: true }
},
{
path: 'usb',
name: 'usb',
component: USBList
},
{
path: 'usb/new',
name: 'usb-new',
component: USBForm,
meta: { requiresAuth: true }
},
{
path: 'usb/:id',
name: 'usb-detail',
component: USBDetail
},
{
path: 'usb/:id/edit',
name: 'usb-edit',
component: USBForm,
meta: { requiresAuth: true }
},
{
path: 'network',
name: 'network',
component: NetworkDevicesList
},
{
path: 'network/new',
name: 'network-new',
component: NetworkDeviceForm,
meta: { requiresAuth: true }
},
{
path: 'network/:id',
name: 'network-detail',
component: NetworkDeviceDetail
},
{
path: 'network/:id/edit',
name: 'network-edit',
component: NetworkDeviceForm,
meta: { requiresAuth: true }
},
{
path: 'reports',
name: 'reports',
component: ReportsIndex
},
{
path: 'calendar',
name: 'calendar',
component: CalendarView
},
{
path: 'settings',
name: 'settings',
@@ -221,6 +330,23 @@ const routes = [
name: 'businessunits',
component: BusinessUnitsList,
meta: { requiresAuth: true, requiresAdmin: true }
},
{
path: 'settings/vlans',
name: 'vlans',
component: VLANsList,
meta: { requiresAuth: true, requiresAdmin: true }
},
{
path: 'settings/subnets',
name: 'subnets',
component: SubnetsList,
meta: { requiresAuth: true, requiresAdmin: true }
},
{
path: 'employees/:sso',
name: 'employee-detail',
component: EmployeeDetail
}
]
}