317 Commits
Author SHA1 Message Date
F4ilji d6c0f48d48 feat(analytics): add site analytics with grouped navigation sections
- Add Analytics container: models, tasks, jobs, controllers, routes, services
- Add analytics config with section groups (structure, institute, content, services)
- Add database tables: analytics_sessions, analytics_hits, analytics_daily_stats
- Add frontend: Analytics page, section detail, chart, overview, navigation components
- Add consent banner and JS tracking service (sendBeacon + Inertia listener)
- Add permission sync for view_analytics, view_any_analytic
- Fix trailing slash URL matching in GetNavigationSectionsTask
- Fix event propagation on expand arrows in navigation sections
- Fix RecordVisitJob to not depend on dropped analytics_geo_cache table
- Replace plain text views/visitors with badge-style icons
- Group navigation sections by category with separate blocks
- Add config-driven non-CMS sections (faculties, divisions, DPO, journals)
- Remove Events, TV, Sveden from analytics sections
2026-09-18 22:18:04 +05:00
F4ilji 7ff860feca feat: block destructive DB commands in production
Listen for CommandStarting event and throw RuntimeException for
migrate:fresh, migrate:refresh, migrate:reset, db:wipe, db:seed
when APP_ENV=production. Prevents accidental data loss even with --force.

Also removes old non-functional closure-based override in routes/console.php.
2026-09-18 02:54:42 +05:00
F4ilji 4a776a42e2 fix: resolve image upload issues in posts
- Dashboard: disable submit button during uploads, show upload errors, guard against pending uploads
- Filament: add maxParallelUploads(1) to fix race condition (filamentphp#13306)
- Filament: add image/webp to gallery acceptedFileTypes, increase resize 30->50
- Dashboard: add image/webp to gallery input accept
- Add missing notifications table migration for Filament databaseNotifications
2026-09-18 02:25:36 +05:00
F4ilji 1853b087f4 chore: update seeders, add MockDataSeeder and AssignAllPermissions command
- DatabaseSeeder: replace old seeders with MockDataSeeder
- RolesSeeder: update role definitions
- Add AssignAllPermissions artisan command
- Register MockDataSeeder in AppServiceProvider
- Register command in ConsoleKernel
2026-09-18 01:39:28 +05:00
F4ilji 02455fbca7 feat(factories): add new factories and update existing ones for all models 2026-09-18 01:39:25 +05:00
F4ilji c7a779d9aa refactor(models): replace HasFactory with HasContainerFactory across all models
Add static $factory property for Porto-style model factory resolution
2026-09-18 01:39:22 +05:00
F4ilji cf18dd660a fix: add missing HasContainerFactory trait to repo 2026-09-18 01:38:01 +05:00
F4ilji cc08cdbc97 fix: 405 error on schedule upload/edit
- Edit.vue: move _method PUT from Inertia options to FormData (Inertia v2 ignores it in options)
- Upload.vue: add forceFormData: true for reliable multipart/form-data
- AccessCheck: add logging when abort() is triggered with non-200 code
- UploadSchedulesController: add request logging for diagnostics
- php.ini: increase max_file_uploads from 20 to 50 for bulk uploads
2026-09-18 01:32:34 +05:00
F4ilji bf77cb634c fix(departments): fix contact info editing, cache invalidation, and pivot data display
- User model: add missing pivot columns (service_email, service_phone, cabinet, sort) to departments_work() and departments_teach() withPivot
- ListDepartmentWorkersAction/TeachersAction: fix where() to wherePivot() for position filters
- Dashboard Workers/Teachers Index.vue: display validation errors in add/edit modals
- Dashboard Workers/Teachers Index.vue: add links to client person pages
- DepartmentCacheService: clear person_* cache when department data changes
- Filament WorkersRelationManager/TeachersRelationManager: fix pivot columns in table (pivot.position etc), add cache clearing on edit/detach/bulk actions
2026-09-18 01:32:27 +05:00
F4ilji e6d223d15c feat(schedules): add 'select all N' across pages
- Add GetAllScheduleIdsAction + GetFilteredScheduleIdsTask
- Add GET /dashboard/schedules/all-ids route returning filtered IDs
- Add selectAllFiltered method to Index.vue
- Button 'Выбрать все N' appears when total > per-page count
2026-08-20 11:31:04 +05:00
F4ilji 24387d6767 feat(schedules): add bulk delete via checkboxes
- Add BulkDeleteSchedulesTask, BulkDeleteSchedulesAction
- Add route DELETE /dashboard/schedules/bulk-destroy
- Add bulkDestroy method to ScheduleController
- Update Index.vue: select all/individual checkboxes, bulk actions bar
- Fix CheckDashboardPermission: replace naive /s$/ regex with Str::singular()
  to resolve irregular plurals (faculties→faculty, categories→category)
2026-08-20 11:16:53 +05:00
F4ilji 63e456088d feat(dashboard): add Roles CRUD with permission-based menu filtering
- Roles CRUD: List/Create/Update/Delete actions, controller, requests
- Roles Vue pages: Index, Create, Edit (Options API, DashboardLayout)
- SidebarNav: filter menu items by user permissions via Inertia shared data
- HandleInertiaRequests: share permissions and roles arrays to frontend
- HttpKernel: register dashboard.permission middleware alias
- SidebarNavItem: add shield-check icon mapping
2026-08-03 10:39:15 +05:00
F4ilji d4ef7daeb1 feat(dashboard): add page export/import functionality
- ExportPageAction: exports page with SEO and section path as JSON
- ImportPageAction: imports page from JSON, resolves section by slug path
- PageController: export/download and import endpoints
- Routes: GET /{page}/export, POST /import
- Index.vue: export button per row, import button in header (local only)
- Import restricted to APP_ENV=local (backend + frontend check)
2026-08-03 10:21:14 +05:00
F4ilji 3860c5d24c fix(permissions): remove direct user permission sync — roles only
UpdateUserAction and CreateUserAction were calling syncPermissions()
which wrote to model_has_permissions table directly. This meant
permissions persisted even after being removed from the role.

Now users only get permissions through their roles.
2026-07-16 14:09:30 +05:00
F4ilji b7259fdd6f refactor(permissions): replace hardcoded route middleware with auto-resolving CheckDashboardPermission
- New middleware extracts permission name from route name automatically
- dashboard.posts.index → view_any_post
- dashboard.admission-campaigns.store → view_any_admission_campaign
- vikon-updates, integration-credentials excluded from check
- Single middleware on parent group instead of 28 individual ones
2026-07-16 12:05:15 +05:00
F4ilji b8fd42d9f8 fix(security): add permission middleware to dashboard routes
Each route group now requires view_any_{resource} permission.
Without the permission, Spatie returns 403 Forbidden.
VIKON updates and integration-credentials remain unprotected.
2026-07-16 11:57:20 +05:00
F4ilji c6ca3258c1 feat(permissions): add dashboard:sync-permissions artisan command
Auto-discovers all dashboard permissions from resource/prefix matrix,
creates missing ones in DB, syncs to super_admin and admin roles.
Run on production after deploy or when adding new menu sections.
2026-07-11 14:17:11 +05:00
F4ilji 4e2105190b fix(tests): replace RefreshDatabase with DatabaseTransactions
- Prevents local DB data loss when running 'php artisan test'
- ViconApiConfigTest uses updateOrCreate to avoid unique constraint
- Delete + Cache::flush for 'not configured' test case
2026-07-10 17:11:27 +05:00
F4ilji 73a0a6fe9c feat(vikon): extract API URL from hardcoded to integration_credentials
- Rename ViconApiToken → ViconApiConfig with token() and apiUrl()
- Replace 9 hardcoded db-nica.ru URLs with dynamic apiUrl()
- Payload now stores both token and api_url with fallback
2026-07-10 16:47:18 +05:00
F4ilji 7748b05547 feat(vikon): move API token from .env to integration_credentials
- Rename VICON_TOKEN → VIKON_API_TOKEN in .env and config
- Add ViconApiToken service reading from integration_credentials table
- Update 3 Vicon services to use ViconApiToken instead of config()
- Config/env kept as fallback for clean migration
2026-07-10 16:43:09 +05:00
F4ilji 520533ef1f fix(ssr): null-safe campaign access to prevent TypeError during SSR 2026-07-06 14:11:38 +05:00
F4ilji 3ee875a6db fix(handler): fallback to HTML when Vite manifest missing during error rendering 2026-07-06 13:41:52 +05:00
F4ilji 9bac98d175 fix(logging): route EmailFetchException to email channel instead of app 2026-07-06 13:39:26 +05:00
F4ilji 65f4220932 fix(vikon): store version in file instead of cache to prevent revert after TTL expiry 2026-07-06 13:28:22 +05:00
F4ilji 9943f7ab90 fix error 2026-07-06 12:35:40 +05:00
F4ilji 769b2ff342 feat(logging): migrate remaining files to app channel — all Log:: calls now use domain channels 2026-07-05 23:32:01 +05:00
F4ilji 6bc1b3e921 feat(logging): migrate Education container to education channel 2026-07-05 23:30:30 +05:00
F4ilji cd9b682994 feat(logging): migrate AI tasks to ai channel 2026-07-05 23:29:39 +05:00
F4ilji 49dd578e50 feat(logging): migrate email pipeline to email channel 2026-07-05 23:28:23 +05:00
F4ilji 41b00fcdae feat(logging): migrate VK API jobs and services to vk channel 2026-07-05 23:26:41 +05:00
F4ilji 720aa4d0ae feat(logging): migrate VikonIntegration to vikon channel 2026-07-05 23:13:51 +05:00
F4ilji e3eda2adbc fix(vikon): revert to api_domain for authorize URL, use vikon_core redirect_uri 2026-07-05 22:39:21 +05:00
F4ilji fd7de347d4 fix: null-safe role check, enable SQLite test DB, improve TinyMCE paste handling 2026-07-05 22:34:04 +05:00
F4ilji bec37c0e22 fix(vikon): use auth_domain for OAuth authorize URL instead of api_domain 2026-07-05 22:31:51 +05:00
F4ilji a32572f5e8 fix(vikon): remove env override for version, use hardcoded default 2026-07-05 17:44:45 +05:00
F4ilji eb142b2513 refactor(vikon): use Redis cache for version instead of file 2026-07-05 15:11:17 +05:00
F4ilji ad8a4d861b fix(vikon): read version from file and update after core update 2026-07-05 15:06:14 +05:00
F4ilji b0ff3bf397 feat(vikon): cleanup _old/_new artifacts after successful sync 2026-07-05 13:58:00 +05:00
F4ilji 416403b6ce debug(vikon): add detailed logging for ZIP size and FM sync stats 2026-07-05 13:33:13 +05:00
F4ilji b9ff255878 fix(vikon): use cURL streaming for ZIP downloads to avoid memory/timeout issues 2026-07-05 13:26:10 +05:00
F4ilji af86841ebc feat(vikon): improve part update UI with per-part status indicators and Russian messages 2026-07-05 12:53:44 +05:00
F4ilji 08c04c5615 feat(vikon): show disabled modules with warning instead of hiding them 2026-07-05 12:34:44 +05:00
F4ilji efce5be699 fix(vikon): use moduleData['id'] instead of array key, handle additional_access_flags 2026-07-05 12:25:15 +05:00
F4ilji 97c4ab99f1 debug(vikon): log raw API response structure for parts mapping 2026-07-05 12:19:14 +05:00
F4ilji a162154f70 fix(vikon): cast API module IDs to int for Vue compatibility 2026-07-05 12:12:04 +05:00
F4ilji 0a5f99e6ae refactor(vikon): remove hardcoded module IDs and use config everywhere 2026-07-05 11:40:02 +05:00
F4ilji 8cf195efb0 refactor(vikon): fetch parts from VIKON API instead of hardcoded config 2026-07-05 11:32:54 +05:00
F4ilji af1fb094d2 fix(vikon): check HTTP status instead of JSON field for part generation check 2026-07-05 10:55:37 +05:00
F4ilji 3d9982e5be fix(vikon): handle numeric status codes from VIKON API (1=completed, -1=failed) 2026-07-05 10:46:02 +05:00
F4ilji 2bf2f4a861 fix(vikon): send POST data as form-urlencoded to match VIKON API expectations 2026-07-05 10:31:40 +05:00