ViewMe
ViewMe

© 2025 ViewMe - Image Management System

memory Memory: N/A
speed CPU: N/A
storage DB: N/A
badge Role: Guest
schedule Server Time: 22:36:42

Changelog - Version 0.2.17

Changelog


[0.2.17] - 2025-12-15


Added

  • User Settings Page (`/user/settings`):
  • New user settings page accessible from header dropdown menu under username.
  • Displays comprehensive user account information including:
  • Personal information (username, full name, email)
  • Account information (role, language preference, status, badge color)
  • Account metadata (last login, created date, updated date)
  • Digital Signature Management:
  • SignaturePad.js integration for drawing signatures directly in browser.
  • Add new signature functionality with canvas-based drawing interface.
  • Edit existing signature functionality with preview display.
  • SVG file storage in `public/uploads/signatures/` directory.
  • Signature preview display with image preview for existing signatures.
  • Automatic cleanup of old signature files when new signature is saved.
  • Responsive signature pad with automatic resize handling for different screen sizes.
  • Security Features:
  • Authentication required (users can only access their own settings).
  • CSRF protection for signature save operations.
  • SVG content validation to prevent XSS and malicious code injection.
  • File size limits (500KB maximum) to prevent DoS attacks.
  • Path traversal protection using `realpath()` validation.
  • Secure file permissions (0644) for uploaded signatures.
  • User ID validation ensures users can only modify their own data.
  • Routes: `/user/settings` (GET), `/user/settings/save-signature` (POST).
  • Translations: Added 20+ translation keys for all UI elements in English and German.
  • Comprehensive PHPDoc documentation for controller and view.
  • Model Controller Refactoring:
  • Extracted common helper methods to reduce code duplication:
  • `prepareModelData()` - Extracts and sanitizes model data from POST requests (used by store/update)
  • `deleteFileIfExists()` - Centralized file deletion logic with path validation
  • `redirectAfterDelete()` - Standardized redirect logic after delete operations
  • `validateLanguage()` - Centralized language code validation (used by previewContract/generateContract)
  • Added comprehensive PHPDoc documentation to all controller methods including parameter types, return values, and usage examples.
  • Enhanced security: All delete operations now use centralized helpers with proper file system security.
  • Models View Refactoring:
  • Extracted CSS from `models/view.php` to external file `/public/assets/css/models-view.css` (~430 lines).
  • Extracted JavaScript from `models/view.php` to external file `/public/assets/js/models-view.js` (~260 lines).
  • Created `window.modelsViewConfig` object pattern (matching shootings/requests pattern) for passing PHP translations and data to external JavaScript.
  • Added comprehensive PHPDoc documentation to view template with feature descriptions and variable documentation.
  • Improved code organization: Better separation of concerns with external assets for caching and maintainability.
  • CSRF Protection Enhancements:
  • Added CSRF tokens to all upload forms (photos, contracts, attachments).
  • Added CSRF tokens to set-primary image form.
  • Added CSRF tokens to booking modal form.
  • Added CSRF tokens to add-to-shooting modal form.
  • All forms now properly protected against CSRF attacks.

Changed

  • ModelController Code Organization:
  • Reduced code duplication in `store()` and `update()` methods by extracting common data preparation.
  • Standardized delete operation patterns across `deleteAttachment()`, `deleteContract()`, and `deleteImage()` methods.
  • Improved maintainability: Helper methods make code easier to understand and modify.
  • Language validation now centralized: Both `previewContract()` and `generateContract()` use the same validation logic.
  • Models View Code Structure:
  • View file reduced from ~870 lines to ~620 lines (29% reduction) by extracting CSS and JavaScript.
  • JavaScript now follows same pattern as other views (shootings.js, requests-view.js) for consistency.
  • CSS can be cached separately from HTML, improving page load performance.
  • JavaScript functions include JSDoc documentation for better IDE support and developer experience.

Technical Details

  • Helper Method Pattern:
  • Helper methods are private and follow single responsibility principle.
  • All helpers include comprehensive PHPDoc with parameter descriptions and return types.
  • Helpers improve testability by isolating specific functionality.
  • External Asset Pattern:
  • CSS and JavaScript files follow naming convention: `{feature}-view.css` and `{feature}-view.js`.
  • Configuration objects passed via `window.{feature}Config` pattern for dynamic PHP data.
  • External files allow browser caching while maintaining dynamic content support.

[0.2.16] - 2025-12-15


Added

  • Date/Time Settings Enhancements:
  • Added live preview functionality for date, time, and datetime format settings.
  • Preview updates in real-time as users type or change format strings.
  • Preview displays formatted output with correct timezone and language translation.
  • Added tooltip on date preview showing format codes (Y, m, d, M, F, l, j) with explanations.
  • Date Format Dropdown:
  • Converted `system.date_format` from text input to dropdown with 13 common formats.
  • Organized formats by region: Europe (d.m.Y, d/m/Y, etc.), USA (m/d/Y, M d, Y, etc.), Asia/ISO (Y-m-d, Y/m/d, etc.).
  • Each option shows user-friendly label with example output.
  • Added "Custom Format..." option for advanced users to enter custom format strings.
  • Custom format input appears when "Custom Format..." is selected.
  • Timezone Initialization:
  • Added `initializeTimezone()` function in `app/Helpers/functions.php` to set PHP's default timezone from database settings.
  • Automatically initializes timezone early in application bootstrap (`public/index.php`).
  • Ensures all `date()` calls and DateTime objects use correct timezone with DST support.
  • Falls back to UTC if database setting cannot be loaded.
  • Comprehensive PHPDoc explaining DST handling, fallback behavior, and impact.
  • Settings Impact Information:
  • Added info button in Date/Time settings tab explaining where settings are used.
  • Modal explains that settings are display-only (do not affect database storage or file operations).
  • Details impact on: Image Views, Request Views, Dashboard, Graphic Dashboard, Shooting Views, Model Views.
  • Clarifies what settings do NOT affect: Database Storage (always UTC), File Operations, API Responses, Data Integrity.
  • Explains timezone setting behavior and DST handling.

Changed

  • Date Format Setting:
  • Changed from text input to dropdown with predefined common formats.
  • Maintains backward compatibility: existing custom formats are preserved and shown as "Custom: {format}".
  • Custom format option allows manual entry for advanced use cases.
  • Settings UI:
  • Added preview boxes below date, time, and datetime format fields.
  • Preview values are right-aligned for better readability.
  • Preview updates automatically when format changes (via JavaScript).
  • DownloadHelper PHPDoc:
  • Enhanced documentation for `downloadWithProfile()` method.
  • Clarified that crop is taken from server image (not client-resized version).
  • Documented that crop coordinates are relative to natural image dimensions.
  • Explained source image priority: final version > original > converted_path.

Technical Details

  • Timezone Initialization:
  • Called in `public/index.php` after helper functions are loaded.
  • Uses `date_default_timezone_set()` to set PHP's default timezone.
  • Validates timezone identifier using `timezone_identifiers_list()`.
  • Errors are logged but do not prevent application startup (falls back to UTC).
  • Preview Endpoint:
  • New endpoint: `/admin/settings/preview-datetime-format`
  • Supports three format types: date, time, datetime.
  • Handles language translation for German (month/day names).
  • Respects 24h/12h format toggle setting.
  • Uses configured timezone for conversion (database stores UTC).
  • Date Format Dropdown:
  • JavaScript handles custom format input visibility toggle.
  • Custom format saves separately from dropdown selection.
  • Preview updates for both dropdown selection and custom input.

[0.2.15] - 2025-12-14


Added

  • Progressive Web App (PWA) Support:
  • Added PWA manifest (`/public/manifest.json`) enabling the application to be installed as a PWA on tablets and mobile devices.
  • Configured for fullscreen display mode to hide browser UI and system bars when possible.
  • Added Android and iOS specific meta tags for optimal fullscreen experience.
  • Implemented Fullscreen API JavaScript for automatic fullscreen mode on page load.
  • Added CSS support for safe area insets (handles device notches and rounded corners).
  • Updated favicon links to use proper icon files from `/public/assets/favicons/`.
  • Black theme color (#000000) for immersive fullscreen experience.
  • PWA Configuration:
  • Viewport configured with `viewport-fit=cover` for edge-to-edge display.
  • iOS status bar style set to `black-translucent` for edge-to-edge display.
  • Cross-browser fullscreen API support (Chrome, Firefox, Safari, Edge).

Technical Details

  • PWA Manifest:
  • Display mode: `fullscreen` (hides browser UI completely when installed as PWA).
  • Icons: 192x192 and 512x512 Android Chrome icons for home screen installation.
  • Orientation: `any` (supports both portrait and landscape).
  • Fullscreen Implementation:
  • JavaScript Fullscreen API with vendor prefix fallbacks (webkit, moz, ms).
  • CSS safe area insets using `env()` function for proper content positioning.
  • Webkit fill-available support for iOS Safari viewport height handling.

[0.2.14] - 2025-12-14


Added

  • Language Management System:
  • Added "Language" tab to `/admin/settings` for managing available system languages.
  • Automatically scans `app/Lang/` directory for available language files.
  • Toggle switch to enable/disable languages globally (persisted in database).
  • Translation comparison tool: Shows translation completeness percentage compared to English source.
  • Visual statistics for each language: Progress bar, missing key count, and expandable list of missing keys.
  • English (source) always displayed at top, other languages sorted alphabetically.
  • User Language Preference:
  • Updated `Translation` helper to prioritize logged-in user's language preference from session/database.
  • Language selection dropdown in User Create/Edit forms (`/admin/users`) is now populated from available language files.
  • User language preference is saved to database and session upon login/update.
  • Priority order for language detection: User Preference > Cookie > Browser > Default.

Changed

  • Translation Helper:
  • Updated `Translation::get()` to check `$_SESSION['auth']['language']` before cookies or browser headers.
  • Ensures immediate language switch when user updates their profile.
  • Admin Settings:
  • Added `SettingsController::compareTranslations()` method to analyze language file completeness.
  • Updated `SettingsController::index()` to scan and prepare language data.

Technical Details

  • Language Settings Storage:
  • Language enabled status stored in `settings` table as `language.{code}.enabled`.
  • Settings are auto-created if they don't exist when toggled.
  • Translation Comparison Logic:
  • Keys are considered missing if they don't exist in the target language file.
  • Keys are flagged as "untranslated" if they exist but have empty values or match the English source text exactly.

[0.2.13] - 2025-12-14


Added

  • Database Backup Cron Endpoint:
  • New endpoint `/admin/settings/create-backup-cron` for automated database backups via cron.
  • Token-based authentication (no user login required).
  • Uses saved database configuration from settings.
  • Returns JSON response with backup results including filename and file size.
  • Backup job tracked in `job_history` table for monitoring.
  • Backup Cron Token Management:
  • New endpoint `/admin/settings/backup-cron-token` to retrieve/generate cron authentication token.
  • Token auto-generated on first use and stored in settings.
  • UI in backup settings tab to display and copy token/URL.
  • Instructions for setting up crontab with curl/wget examples.
  • Footer Job Status Monitoring:
  • Added "System Jobs" section in footer showing job execution status.
  • Displays catalog import and database backup job status with color-coded indicators:
  • Green: Job ran within last 24 hours (normal)
  • Yellow: Job ran 24-48 hours ago (overdue)
  • Red: Job hasn't run in 48+ hours (critical)
  • Collapsible section to save vertical space.
  • When collapsed: Shows minimal view with icon + job name on same line as header.
  • When expanded: Shows full details with status message and time since last run.
  • State persisted in localStorage (defaults to collapsed).
  • Horizontal card layout (left to right) when expanded.
  • JobStatusHelper:
  • New helper class for checking job execution status.
  • `getJobStatus()` - Get status for a specific job type with configurable time windows.
  • `getMultipleJobStatuses()` - Get status for multiple jobs at once.
  • `formatHoursAgo()` - Format time duration for display (minutes/hours/days).
  • Handles edge cases: never run, never succeeded.

Changed

  • Backup Job Tracking:
  • All database backups (manual and cron) now tracked in `job_history` table.
  • Job history includes file size, filename, and duration metadata.
  • Job history updated on success/failure for monitoring.
  • Footer Layout:
  • System Jobs section is collapsible to save vertical space.
  • Collapsed view shows everything on one line: "System Jobs [toggle] ✓ Catalog Import ✓ Database Backup".
  • Expanded view shows full job cards arranged horizontally.
  • Improved responsive design for mobile devices.

Technical Details

  • Job Status Display:
  • Status determined by time since last successful job completion.
  • Configurable warning and error thresholds per job type.
  • Color-coded indicators for quick visual status assessment.
  • Collapsible Footer Section:
  • Uses CSS classes and JavaScript for smooth expand/collapse.
  • State persisted in localStorage for user preference.
  • Minimal collapsed view saves significant vertical space.
  • Backup Cron Security:
  • Uses `hash_equals()` for timing-safe token comparison.
  • Token stored securely in settings, auto-generated if missing.
  • Returns 403 for invalid/missing tokens.

[0.2.12] - 2025-12-14


Added

  • Job History System:
  • Created generic `job_history` database table for tracking cron jobs, background workers, and scheduled tasks.
  • New `JobHistory` model with comprehensive methods for job lifecycle management:
  • `startJob()` - Initialize job tracking with metadata
  • `completeJob()` - Mark job as successful with duration and results
  • `failJob()` - Mark job as failed with error message
  • `updateMetadata()` - Update job metadata during execution
  • `getByProgressKey()` - Find job by progress tracking key
  • `getRecentByType()` - Get recent jobs filtered by type
  • `getRecent()` - Get all recent jobs with optional status filter
  • `getStatistics()` - Get job statistics (success rate, avg duration, etc.)
  • Table supports flexible metadata storage (JSON) for job-specific data.
  • Tracks job type, status, duration, error messages, and trigger source (user/cron/system).
  • Catalog Import Cron Endpoint:
  • New endpoint `/admin/catalog/import-cron` for automated catalog imports via cron.
  • Token-based authentication (no user login required).
  • Supports `force_update` parameter for forcing field updates.
  • Uses saved catalog configuration (URL, field mappings) from settings.
  • Returns JSON response with import results or progress key for background jobs.
  • Cron Token Management:
  • New endpoint `/admin/catalog/cron-token` to retrieve/generate cron authentication token.
  • Token auto-generated on first use and stored in settings.
  • UI in catalog settings tab to display and copy token/URL.
  • Catalog Import UI Enhancements:
  • Added "Scheduled Import (Cron)" section in catalog settings tab.
  • "Show Token" button to display cron authentication token.
  • Copy buttons for token and cron URL.
  • Instructions for setting up crontab with curl/wget examples.
  • Warning about saving configuration before setting up cron.
  • Modal Confirmation for Catalog Import:
  • Replaced browser `confirm()` dialog with styled modal using `ModalHelper.confirm()`.
  • Better UX with consistent application styling.
  • Fallback to browser confirm if ModalHelper not available.

Changed

  • Catalog Import Job Tracking:
  • All catalog imports (manual and cron) now tracked in `job_history` table.
  • Job history ID stored in worker job file for background job completion tracking.
  • Worker script updates job history on success/failure.
  • Job metadata includes import statistics (imported, updated, failed counts).
  • Catalog Import Error Handling:
  • Improved error logging and job history tracking for failed imports.
  • Job history updated at all failure points (XML fetch, parsing, import errors).

Technical Details

  • Job History Table Schema:
  • Fields: `job_type`, `job_name`, `status`, `triggered_by`, `triggered_by_type`, `started_at`, `completed_at`, `duration_seconds`, `progress_key`, `error_message`, `metadata` (JSON).
  • Indexes on `job_type`, `status`, `started_at`, `triggered_by`, `progress_key` for efficient queries.
  • Foreign key to `users` table for user-triggered jobs.
  • Cron Endpoint Security:
  • Uses `hash_equals()` for timing-safe token comparison.
  • Token stored securely in settings, auto-generated if missing.
  • Returns 403 for invalid/missing tokens.
  • Migration Script:
  • `create_job_history_table.php` - Creates job_history table with proper indexes.
  • Checks for existing table before creation.

[0.2.11] - 2025-12-14


Added

  • StatusHelper - Centralized Status Management System:
  • Created comprehensive `StatusHelper` class to centralize all status-based business logic, button visibility, and action permissions.
  • Provides single source of truth for request, shooting, and image status rules.
  • Methods for checking action permissions: `canEditRequest()`, `canPlanShooting()`, `canSendToGraphics()`, `canMarkShootingDone()`, `canEditShooting()`, `canChangeShootingStatus()`.
  • Methods for image status management: `canApproveImage()`, `canRejectImage()`, `canResetImageToPending()`, `canUploadImageVersion()`, `canDeleteImageVersion()`.
  • Status grouping methods: `isBlockedStatus()`, `isAdvancedStatus()`, `allRequestsAdvanced()`, `hasAnyRequestAdvanced()`.
  • Image badge visibility methods: `shouldShowImageStatusBadge()`, `shouldHideImageStatusBadgeForRequest()`, `shouldShowGraphicsAtWorkBadge()`, `getImageStatusIcon()`.
  • Request action visibility methods: `shouldHideRequestActions()`, `shouldShowImageStatusBanner()`, `shouldShowImageWorkflowActions()`.
  • Comprehensive PHPDoc documentation for all methods with usage examples.
  • Image Status Badge Management:
  • Added logic to hide approved/rejected badges on images when associated request is "Sent to graphics" or beyond.
  • Added "Graphics at work" badge that displays when request is in graphics workflow (`sent_to_graphics`, `graphics_claimed`, `graphics_finished`, `sent_to_shop`).
  • Badge priority system: Final version badge > Graphics at work badge > Status badges.
  • Badge automatically appears in `/images` view when images are linked to requests in graphics workflow.
  • Added translation keys: `images.graphics_at_work` and `images.graphics_at_work_tooltip`.
  • Request Action Button Visibility:
  • "Plan Shooting" and "Edit Request" buttons are now automatically hidden when request status is "Shooting Completed" (`shooting_done`).
  • "Plan Shooting" and "Edit Request" buttons are now automatically hidden when request status is "Sent to graphics" (`sent_to_graphics`).
  • Buttons are also hidden for all advanced statuses: `graphics_claimed`, `graphics_finished`, `sent_to_shop`, `completed`, `cancelled`.
  • Centralized logic ensures consistent behavior across `/requests` list view and `/requests/view/{id}` detail view.

Changed

  • StatusHelper Integration:
  • Refactored `/requests` index view to use `StatusHelper` methods instead of inline status checks.
  • Refactored `/requests/view` detail view to use `StatusHelper` methods instead of inline status checks.
  • Refactored `/shootings/view` detail view to use `StatusHelper` methods for status-based logic.
  • Refactored `/images/view` detail view to use `StatusHelper` for image action permissions and badge visibility.
  • Refactored `image-card.php` component to use `StatusHelper` for badge display logic.
  • All status-based conditional logic now centralized in `StatusHelper` for easier maintenance and consistency.
  • Image Model Enhancement:
  • Updated `Image::getForUser()` method to include `request_status` via LEFT JOIN with `photo_requests` table.
  • Enables badge visibility logic based on request status in image gallery views.

Technical Details

  • StatusHelper Architecture:
  • Helper class uses static methods for easy access throughout the application.
  • Status arrays defined as private static properties for easy modification.
  • Methods follow consistent naming convention: `can*()` for permissions, `should*()` for visibility, `is*()` for status checks.
  • All methods include role-based permission checks integrated with existing permission system.
  • Badge Display Logic:
  • Image status badges respect request workflow status.
  • Graphics workflow badges provide clear visual indication of work in progress.
  • Badge display logic is extensible for future workflow stages.

[0.2.10] - 2025-12-13


Added

  • Open Requests Modal Enhancements:
  • Added priority-based filtering with filter buttons in modal header (All, Urgent, High, Normal).
  • Filter buttons display counts inline (e.g., "priority_high 1 Urgent").
  • Priority color borders on request items (red=urgent, orange=high, default=normal) for quick visual identification.
  • Request item tooltips showing detailed information:
  • Who made the request (initial_requestor)
  • Request Date (formatted as d.m.Y)
  • Requested For (requester_code)
  • Model requirement (Yes/No based on model_requirements)
  • Catalog information
  • Conditional tooltip display: only shows fields that have data (no "-" placeholders).
  • "Select all" button converted to modern button style with dynamic icon states (check_box, check_box_outline_blank, indeterminate_check_box).
  • Selection count integrated into "Use selected" button text (format: "0 / 3 selected - Use selected").
  • Improved modal layout: filter buttons in header, "Select all" in footer left, action buttons in footer right.
  • Shootings View Refactoring:
  • Extracted CSS from `shootings/index.php` to `/public/assets/css/shootings.css` (~787 lines).
  • Extracted JavaScript from `shootings/index.php` to `/public/assets/js/shootings.js` (~374 lines).
  • Created reusable `shooting-card.php` component to eliminate duplication between scheduled/unscheduled cards.
  • Created `ShootingHelper` class with methods: `extractArticleNumbers()`, `extractProductNames()`, `getStatusInfo()`, `getDisplayTitle()`.
  • Replaced hardcoded date helpers with `DateHelper` class for consistent formatting and translation.
  • Added comprehensive PHPDoc comments throughout the shootings index view.
  • Open Requests Modal Improvements:
  • "Open Requests" modal now shows "All Done" message with large green icon when no open requests exist.
  • "Use selected" button hidden when there are no open requests.
  • Modal title simplified (removed priority counts, moved to filter buttons).
  • Filter buttons only show if they have items (e.g., Urgent button only appears if urgentCount > 0).

Changed

  • Modal Helper:
  • Added `allowHtmlTitle` option to `Modal::render()` to support HTML in modal titles.
  • Modal titles can now include HTML elements (icons, badges, etc.) when `allowHtmlTitle => true`.
  • Shootings Index View:
  • Refactored to use external CSS and JavaScript files for better maintainability and caching.
  • Replaced inline date formatting functions with `DateHelper` class methods.
  • Replaced duplicated shooting card HTML with reusable component includes.
  • Improved code organization and maintainability.
  • Button Styling:
  • "Select all" button now uses `btn-secondary` class to match "Close" button styling.
  • Consistent font size, color, and padding across all footer buttons.

Technical Details

  • Priority Filtering:
  • JavaScript filtering function `filterOpenRequestsByPriority()` filters and sorts visible items.
  • Filter state persists during modal session, resets to "All" when modal is reopened.
  • Selection count and "Select all" only affect visible items when filtering.
  • Tooltip Implementation:
  • Uses `Tooltip::renderAttribute()` with `allowHTML => true` for multi-line content.
  • Fields are conditionally included only if they have non-empty values.
  • Tooltip attribute is only added if at least one field has data.
  • Component Architecture:
  • Shooting card component accepts variables: `$shooting`, `$isUnscheduled`, `$startTimestamp`, `$endTimestamp`, `$statusClass`.
  • Component uses `ShootingHelper` and `DateHelper` for data extraction and formatting.
  • Component is fully reusable and can be included in other views.

[0.2.9] - 2025-12-13


Added

  • Dashboard Refactoring - Service Layer Architecture:
  • Extracted dashboard business logic into dedicated service classes for better separation of concerns.
  • Created `DashboardActivityService` for aggregating and managing activity feed (uploads, ratings, comments).
  • Created `DashboardStatsService` for role-based statistics calculation with caching support.
  • Created `DashboardGraphicJobsService` for graphic jobs management and webshop action tracking.
  • Created `DashboardShootingService` for shooting data aggregation, deduplication, and sorting.
  • Reduced `DashboardController::index()` from 274 lines to 73 lines (73% reduction).
  • Database Query Optimization:
  • Fixed N+1 query problems in graphic jobs service by implementing batch loading methods.
  • Added `Image::getVersionsBatch()` to load versions for multiple images in a single query.
  • Added `Image::getLinkedImagesBatch()` to load linked images for multiple requests in one query.
  • Added `PhotoRequest::getWorkflowTransitionsBatch()` to load workflow transitions for multiple requests.
  • Query reduction: From ~150+ queries to ~3 queries for 50 graphic jobs (~98% reduction).
  • Dashboard Statistics Caching:
  • Implemented file-based caching system using `Cache` helper class.
  • Dashboard statistics are cached for 5 minutes (configurable TTL) to improve performance.
  • Cache keys are role-specific and user-specific: `dashboard_stats_{role}_{userId}`.
  • Added cache invalidation methods: `invalidateCache()`, `invalidateCacheForRole()`, `invalidateAllCache()`.
  • Added `getStatsHash()` method for efficient change detection (useful for SSE implementations).
  • Performance improvement: From ~10-20 database queries per load to 0 queries on cache hit.
  • Cache storage location: `storage/cache/` directory.
  • Role-Based Strategy Pattern:
  • Implemented strategy pattern to eliminate role check duplication in dashboard statistics.
  • Created `DashboardStatsProviderInterface` and `AbstractDashboardStatsProvider` base classes.
  • Created role-specific providers:
  • `PhotographerDashboardStatsProvider` - Photographer-specific stats
  • `GraphicDashboardStatsProvider` - Graphic-specific stats (also provides `graphics_claimed` for purchase role)
  • `PurchaseDashboardStatsProvider` - Purchase-specific stats
  • `ShopManagerDashboardStatsProvider` - Shop manager-specific stats
  • `AdminDashboardStatsProvider` - Admin-only stats
  • Created `DashboardStatsProviderFactory` to return all applicable providers for a role.
  • Eliminated repeated `hasRole()` checks throughout the service layer.
  • Documentation:
  • Created `Docs/DASHBOARD-CACHE.md` with caching usage guide and troubleshooting.
  • Created `Docs/DASHBOARD-SSE-PLAN.md` with Server-Sent Events implementation plan for future real-time updates.

Changed

  • Dashboard Controller:
  • Refactored to use service classes instead of direct model access.
  • Controller now acts as a thin orchestration layer (73 lines vs 274 lines).
  • Improved maintainability and testability through dependency injection pattern.
  • Dashboard Statistics Service:
  • Moved raw SQL query from service to `Image::getShopQueueStats()` model method.
  • Replaced role check logic with strategy pattern using role-specific providers.
  • Removed unused dependencies (models/services moved to providers).
  • Statistics calculation now delegates to appropriate providers based on role.
  • Code Organization:
  • Created `app/Services/Dashboard/` directory for dashboard-related providers.
  • Better separation of concerns: services handle business logic, models handle data access.
  • Improved code reusability: services can be used by other controllers or SSE endpoints.

Technical Details

  • Service Layer Architecture:
  • All dashboard data fetching is now handled by dedicated service classes.
  • Services are independent and can be tested in isolation.
  • Services can be reused by other controllers or future SSE endpoints.
  • Batch Loading:
  • Batch loading methods group related queries to eliminate N+1 problems.
  • Methods return data grouped by ID for easy lookup in application code.
  • All batch methods include comprehensive PHPDoc documentation.
  • Caching Strategy:
  • Cache uses JSON file storage with expiration timestamps.
  • Automatic cache expiration after TTL (default: 5 minutes).
  • Cache can be manually invalidated when data changes.
  • Cache keys are sanitized for filesystem safety.
  • Strategy Pattern Implementation:
  • Each role has its own provider class encapsulating role-specific logic.
  • Factory pattern returns all applicable providers (webadmin/webmaster get multiple providers).
  • Providers can be easily extended or modified without affecting other roles.
  • Follows SOLID principles (Single Responsibility, Open/Closed, Dependency Inversion).

[0.2.8] - 2025-12-13


Added

  • ICC Profile Detection and Storage:
  • Added automatic ICC profile detection for images during import/conversion and version uploads.
  • ICC profile information (description and color space) is detected using libvips and ExifTool.
  • Profile data is stored in `images` table (`icc_profile_description`, `color_space` columns) for original images.
  • Profile data is stored in `image_versions` table for uploaded versions (shop and final).
  • ICC profile badge displayed on image detail pages (`/images/:id`) when profile is detected.
  • Badge shows truncated profile description and color space (e.g., "ICC: Generic RGB Profile / sRGB").
  • Badge uses cyan/teal color scheme (#00bcd4) to distinguish from other badges.
  • Tooltip displays full profile information including uploader details for final versions.
  • Badge prioritizes final version ICC profile over original image profile.
  • Database migration scripts: `add_icc_profile_columns.php` (images table), `add_icc_profile_to_image_versions.php` (image_versions table).
  • Comprehensive PHPDoc documentation for ICC profile detection methods.
  • Image Cropping with Export Profiles:
  • Added crop aspect ratio setting per export profile (square, 4:3, 16:9, etc.).
  • Crop aspect ratio is stored in `export_profiles` table (`crop_aspect_ratio` column).
  • Visual indicator (crop icon) displayed on download buttons when a profile has a crop aspect ratio set.
  • Crop icon also shown in admin settings profile list with tooltip.
  • Integration with Cropper.js for client-side image cropping interface.
  • Crop modal opens automatically when downloading with a profile that has an aspect ratio set.
  • Crop coordinates are captured from Cropper.js and sent to backend as query parameters.
  • Backend cropping implemented using libvips `extract_area()` method.
  • Cropping is applied before resize/format conversion/quality settings (processing order: Crop → Resize → Format → Quality).
  • Crop coordinates are validated and clamped to image bounds for safety.
  • Comprehensive PHPDoc documentation for cropping functionality.
  • Implementation guide for future "Save Copy" feature (saving cropped images as versions).
  • Documentation:
  • Created `Docs/CROP-SAVE-COPY-IMPLEMENTATION.md` with detailed implementation guide for saving cropped images as permanent versions.
  • Updated PHPDoc for `ImageController::downloadWithProfile()` with crop parameter documentation.
  • Updated PHPDoc for `DownloadHelper::downloadWithProfile()` with detailed crop parameter descriptions and examples.

Changed

  • Export Profile Settings:
  • Moved crop aspect ratio from global setting to per-profile setting in `export_profiles` table.
  • Updated admin settings UI to include crop aspect ratio dropdown in "Add/Edit Export Profile" modal.
  • Profile list in admin settings now displays crop icon when crop aspect ratio is set.
  • Download Buttons:
  • Download buttons now show crop icon when profile has a crop aspect ratio.
  • Download button text alignment changed to center for better visual balance.
  • Added `data-crop-aspect-ratio` attribute to download buttons for JavaScript handling.

Technical Details

  • Crop coordinates from Cropper.js are relative to natural image dimensions (using `getData(true)`).
  • Libvips `extract_area()` is used for high-performance cropping before other transformations.
  • Temporary cropped files are created during processing and cleaned up after download.
  • Crop parameters are passed via query string: `?crop_x=100&crop_y=200&crop_width=800&crop_height=600`.

[0.2.7] - 2025-12-12


Added

  • Final Version Upload System:
  • Added ability to upload final versions of images from graphic dashboard (`/graphic`) and image detail pages (`/images/:id`).
  • Final versions can be uploaded as PNG, JPEG, or TIFF files.
  • Reused existing upload modal for both shop versions and final versions with dynamic endpoint switching.
  • Final version uploads are stored in `image_versions` table with `version_type = 'final'`.
  • Final version filename prefix: `final_` (e.g., `final_314_1234567890.png`).
  • Final version badge displayed on graphic dashboard and image gallery when final version exists.
  • Final version tooltip shows uploader name and upload date.
  • Source format badge displays the format of the final version file (e.g., "Source: PNG", "Source: TIFF") when a final version exists.
  • Source format badge tooltip shows final version information including uploader and date.
  • Final Version Priority System:
  • Final versions automatically become the main image throughout the system when they exist.
  • Priority order for display and downloads: final version > original (shop versions are excluded).
  • New `Image::getDisplayImagePath()` method returns the best available image path with version priority.
  • New `Image::getDisplayImageUrl()` method returns the best available image URL with version priority.
  • Updated `getImageUrl()` helper function to use final version priority.
  • All image views, downloads, and serving endpoints now use final version if available.
  • Download priority: final version > original (shop versions never prioritized for downloads).
  • Image Detail Page Enhancements:
  • Added final version upload card on `/images/:id` page (separate from shop version upload).
  • Original image now appears as first entry in "Versions" section even if `file_path` is null.
  • Workflow card is hidden when image has a final version (not needed at that stage).
  • Approved/rejected status banners are hidden when image has a final version.
  • "Download Original" button now prioritizes final version if it exists, otherwise downloads original file.
  • Source format badge shows final version format when final version exists.
  • Graphic Dashboard Improvements:
  • Final version badge displayed on job cards in both detail and list views.
  • Badge positioning updated: shop version badge (top-left), final version badge (top-right).
  • Preview image size increased by 20% (150px → 180px) to accommodate badges.
  • Final version tooltip includes uploader name and upload date with proper line breaks.
  • Image Gallery Enhancements:
  • Final version badge displayed on image cards in main gallery (`/images`).
  • Source format badge shows final version format when final version exists.
  • Status badges (approved/rejected/pending) are hidden when final version exists (replaced by "Final Ready" badge).

Changed

  • Image Display Priority:
  • Updated all image display logic to prioritize final versions over original images.
  • `ImageController::serveConverted()` now serves final version if available.
  • `ImageController::downloadConverted()` now downloads final version if available.
  • `ImageController::downloadOriginal()` now downloads final version if available, otherwise original.
  • `DownloadHelper::downloadWithProfile()` now uses final version as source if available.
  • Upload System:
  • Consolidated upload modals: single modal now handles both shop version and final version uploads.
  • Upload endpoint dynamically switches based on upload type (`/upload-shop-image` or `/upload-final`).
  • JavaScript handlers updated to support both upload types with proper endpoint routing.
  • Upload progress bar resets correctly when modal is closed.
  • Source Format Detection:
  • Source format badge now reads format from final version file (filename or file_path) when final version exists.
  • Falls back to original image source format only if final version format cannot be determined.
  • Tooltip for source format badge shows final version information when final version exists.
  • PHPDoc Documentation:
  • Updated PHPDoc for `Image::getDisplayImagePath()` and `Image::getDisplayImageUrl()` methods.
  • Updated PHPDoc for `Image::getVersions()` method with comprehensive field descriptions.
  • Updated PHPDoc for `ImageVersionController::upload()` method documenting version_type parameter.
  • Updated PHPDoc for `getImageUrl()` helper function with priority order and shop version exclusion.
  • Updated PHPDoc for `ImageController::downloadOriginal()` method.
  • All PHPDoc blocks now document final version priority and shop version exclusion.

Fixed

  • Fixed source format badge showing original image format instead of final version format.
  • Fixed tooltip not displaying final version uploader information correctly (added proper HTML line breaks).
  • Fixed undefined variable warnings in `GraphicController` when checking for final versions.
  • Fixed upload area ID conflicts when multiple upload modals exist on the same page.

[0.2.6-beta] - 2025-12-11


Added

  • Articles Feature:
  • Complete Articles management system with MVC architecture (Model, Controller, Views).
  • Article listing page (`/articles`) with search, pagination, and filtering capabilities.
  • Article detail pages showing full article content, related product information, and linked images.
  • Product detail pages (`/articles/product/:id`) for products without articles yet, displaying all product information and associated images.
  • Search functionality across articles, products, and images by article number, product name, or title.
  • Autocomplete search suggestions with real-time results and "create product" option for numeric searches.
  • "Recently Added" section showing the last 10 unique product article numbers with their images when no search is active.
  • Create product modal for adding new products directly from search when article number is not found.
  • Full internationalization support with English and German translations for all article-related UI elements.
  • Image URL helper function (`getImageUrl()`) for consistent TIFF file handling across all views.
  • Performance optimizations:
  • Fixed N+1 query problem in `getRecentImagesByArticleNumber()` (reduced from 200+ queries to 3 queries).
  • Added database indexes for products, images, and articles tables to improve query performance.
  • Optimized search queries with prefix matching for better index usage.
  • Performance improvement: 30-80 seconds → 1.5-4 seconds with 10,000+ records and 10 concurrent users.
  • Database indexes script (`optimize_articles_indexes.php`) for one-time index creation.
  • Comprehensive PHPDoc documentation for all Article model methods and controller actions.
  • Routes: `/articles`, `/articles/:id`, `/articles/product/:id`, `/articles/suggestions`, `/articles/product/create`.
  • Multiple Products per Image Feature:
  • Database schema enhancement with junction tables (`image_products`, `image_articles`) for many-to-many relationships.
  • Migration script (`add_image_products_junction_table.php`) to create junction tables with foreign keys and indexes.
  • Image model methods for managing product relationships:
  • `getProducts($imageId)` - Retrieves all products linked to an image (primary + secondary).
  • `getPrimaryProduct($imageId)` - Gets the primary product for an image.
  • `addProduct($imageId, $productId, $isPrimary, $displayOrder)` - Adds a product to an image.
  • `removeProduct($imageId, $productId)` - Removes a product from an image.
  • `getProductCount($imageId)` - Counts total products linked to an image.
  • Updated `getForProduct()` method to include images from both `images.product_id` and `image_products` junction table.
  • Product management UI on image detail pages (`/images/:id`):
  • "Manage Products" card in sidebar with autocomplete search for products.
  • Search by article number or product name with real-time suggestions.
  • Create new products directly from search if article number doesn't exist.
  • Add/remove products with visual product badges showing primary status.
  • Real-time updates of product list after add/remove operations.
  • Visual indicators for multiple products:
  • Product badges on image detail pages showing all linked products.
  • Multi-product indicator badges on image thumbnails (shows count when > 1 product).
  • Primary product highlighted with star icon and primary color.
  • Product badges displayed on article detail pages, product detail pages, and image galleries.
  • API endpoints for product management:
  • `GET /images/:id/products/suggestions` - Autocomplete product search.
  • `POST /images/:id/products/add` - Add product to image.
  • `POST /images/:id/products/remove` - Remove product from image.
  • Backward compatibility maintained: existing `images.product_id` relationships continue to work.
  • Comprehensive PHPDoc documentation for all new Image model and ImageController methods.
  • English and German translations for all product management UI elements.
  • Documentation files:
  • `Docs/IMAGES-MULTIPLE-PRODUCTS-SOLUTION.md` - Database design and implementation details.
  • `Docs/IMAGES-MULTIPLE-PRODUCTS-FRONTEND.md` - Frontend implementation examples and UI components.
  • Main Layout Refactoring:
  • Extracted CSS from `main.php` to separate file `/public/assets/css/layout.css` (728 lines of layout-specific styles).
  • Created JavaScript modules: `error-handler.js`, `theme-init.js`, and `layout.js` for better code organization.
  • Created `ChangelogHelper` class for parsing and loading changelog markdown content.
  • Split main layout into reusable partial components:
  • `partials/header.php` - Header structure
  • `partials/navigation.php` - Navigation menu with collapsible sections
  • `partials/header-actions.php` - Header right-side actions (reports, admin, theme toggle, user menu)
  • `partials/footer.php` - Footer with language switcher and system stats
  • `partials/debug-panel.php` - Frontend debug panel for permission checks
  • `partials/debug-permissions.php` - Debug permissions section
  • `partials/debug-navigation.php` - Debug navigation visibility section
  • `partials/modals.php` - Changelog and dependencies modals
  • `partials/dependencies-content.php` - Dependencies modal content
  • Reduced `main.php` from 878 lines to 84 lines (90% reduction) for improved maintainability.
  • Download Helper with Configurable Export Profiles:
  • Added "Downloads" tab to `/admin/settings` for managing export/download profiles for images.
  • Export profiles support configurable settings: format (jpeg, png, webp, avif), quality (1-100%), dimensions (e.g., 1280px, 800px, or "Keep size"), progressive JPEG encoding, title, Material Icons icon, notes, and active/inactive status.
  • Each profile has a custom filename template system supporting variables: `{filename}`, `{profile_title}`, `{format}`, `{dimension}`, `{quality}`, `{timestamp}`, `{date}`, `{id}`, `{article_number}`, `{product_title}`, `{number}`, `{sequence}`.
  • Template variables are validated client-side with live preview and error checking.
  • Template help modal explains available variables and provides examples.
  • Filename template preview uses real database data when template includes database-dependent variables (article_number, product_title, etc.).
  • Global filename settings: ASCII/UTF-8 encoding toggle and case setting (original/lowercase/uppercase) that apply to all export profiles.
  • ASCII conversion with proper transliteration: converts international characters to ASCII equivalents (ö→oe, ä→ae, ü→ue, é→e, etc.) using manual mapping before iconv for consistency.
  • Automatic dot stripping: dots are removed from article numbers and product titles (except the dot before file extension).
  • Download buttons are dynamically rendered on image detail pages (`/images/:id`) based on active export profiles.
  • Setting to show/hide "Download Original" button on image pages.
  • Backend endpoint (`/images/:id/download/profile/:profileId`) handles image conversion and download according to profile settings.
  • Preview filename endpoint (`/admin/export-profiles/preview-filename`) generates real-time previews with database data and applies encoding/case settings.
  • Database table: `export_profiles` stores profile configurations including `filename_template` field.
  • Routes: `/admin/export-profiles/list`, `/admin/export-profiles/:id`, `/admin/export-profiles/create`, `/admin/export-profiles/:id/update`, `/admin/export-profiles/:id/delete`, `/admin/export-profiles/preview-filename`.
  • Migration scripts: `add_export_profiles_table.php`, `add_download_show_original_setting.php`, `add_naming_scheme_to_export_profiles.php`, `add_filename_settings.php`.

Changed

  • Main Layout Structure:
  • Refactored `app/Views/layouts/main.php` to use component-based architecture with partial includes.
  • Moved inline JavaScript to external files for better caching and maintainability.
  • Improved code organization following separation of concerns principle.
  • Fixed changelog path in modals partial (corrected relative path from partials directory).
  • Image Download System:
  • Removed hardcoded "Download Original", "Download Converted", and "Download Full" buttons from image detail pages.
  • Replaced with dynamic export profile buttons that are configurable via admin settings.
  • Download filenames are now generated using configurable templates instead of fixed naming scheme.
  • PHPDoc Documentation:
  • Added comprehensive PHPDoc to `DownloadHelper` class methods: `downloadWithProfile()`, `generateFilenameFromTemplate()`, `convertToAscii()`, `getImageSequenceNumber()`.
  • Added PHPDoc to `ExportProfileController` methods: `previewFilename()`, `generatePreviewFromSample()`, `generateFilenamePreview()`, `convertToAscii()`, `getImageSequenceNumber()`.
  • Added PHPDoc to `ImageController` methods: `show()`, `getProductSuggestions()`, `addProduct()`, `removeProduct()`.
  • Added PHPDoc to `Image` model methods: `getProducts()`, `getPrimaryProduct()`, `addProduct()`, `removeProduct()`, `getProductCount()`, `getForProduct()`.
  • All PHPDoc blocks include detailed parameter descriptions, return values, examples, and implementation notes.

[0.2.5-beta] - 2025-12-11


Added

  • mPDF Font Management System:
  • Added "Fonts" tab to `/admin/settings` for managing custom fonts used in mPDF PDF generation.
  • Font upload functionality supporting TTF and OTF font file formats (maximum 10MB per file).
  • Font files stored in `storage/fonts/mpdf/` directory (outside vendor directory to prevent composer update conflicts).
  • Font list display with file details: filename, size, and modification date.
  • Inline font preview on font list showing sample text rendered with each uploaded font.
  • Full font preview page with comprehensive examples:
  • Multiple text sizes (large, regular, small)
  • Alphabet display (uppercase and lowercase)
  • Numbers display
  • Pangram examples
  • Sample paragraph text
  • Font deletion functionality with confirmation dialog.
  • Font serving endpoint (`/admin/settings/serve-font`) with proper MIME types and CORS headers for @font-face usage.
  • Font preview endpoint (`/admin/settings/preview-font`) generating HTML with @font-face CSS and sample text.
  • Security features: filename sanitization, directory traversal protection, file type validation (extension and MIME type).
  • Flexible MIME type validation: allows various font MIME types while rejecting obviously wrong file types.
  • Auto-loading of fonts when Fonts tab is activated.
  • Routes: `/admin/settings/upload-font` (POST), `/admin/settings/list-fonts` (GET), `/admin/settings/delete-font` (POST), `/admin/settings/serve-font` (GET), `/admin/settings/preview-font` (GET).
  • Background Image Processing System:
  • Migrated blocking image upload/import process to asynchronous background worker system.
  • Created `image_processing_queue` table to store processing jobs with status tracking (pending, processing, completed, failed).
  • New `ImageProcessingQueue` model for queue management with methods: `enqueue()`, `getNextJob()`, `markProcessing()`, `markCompleted()`, `markFailed()`, `resetStuckJobs()`.
  • New `ImageProcessingQueueManager` helper class to simplify job queuing and status checking.
  • CLI worker script (`image_processing_worker.php`) processes jobs asynchronously:
  • Handles image conversion, thumbnail generation, histogram/palette analysis, and EXIF extraction.
  • Automatically updates image records in database when processing completes.
  • Supports retry logic and error handling with detailed logging.
  • Automatic worker triggering: `ImageController` and `NasController` automatically start background workers after queuing jobs.
  • Images are immediately created with `status='processing'` and processed in background, improving web request responsiveness.

  • Auto-Refresh for Processing Images:
  • Added automatic polling system on `/images` page to check processing status every 2 seconds.
  • New API endpoint `/images/:id/check-status` returns current image status and thumbnail availability.
  • JavaScript automatically detects when processing completes and updates the display:
  • Hides loader animation and shows thumbnail image.
  • Updates status badge from "Processing" to "Pending".
  • Updates data attributes for seamless UI transitions.
  • Polling stops automatically after 2 minutes (60 attempts) to prevent infinite checking.
  • Works for both uploaded images and imported images from NAS.

  • Processing Image Loader Animation:
  • Added visual loader animation (`.lds-grid`) for images with `status='processing'` on image list page.
  • Uses same CSS animation as NAS browse page for consistency.
  • Displays animated grid loader instead of static placeholder when thumbnail is not yet available.
  • Status badge shows "sync" Material Icon for processing images.

Changed

  • Image Upload/Import Flow:
  • `ImageController::upload()` now creates image record immediately with `status='processing'` and queues background job instead of processing synchronously.
  • `NasController::import()` now queues processing jobs for each file instead of processing immediately.
  • Both controllers trigger background workers automatically after queuing jobs.
  • Web requests return immediately with success response, improving user experience.

  • BaseModel Enhancement:
  • Modified `BaseModel::create()` to filter out `null` values from input data before insertion.
  • Prevents database errors when `null` is explicitly passed for columns defined as `NOT NULL` without default values.
  • Allows initial image records to be created with minimal required fields, with worker updating remaining fields later.

[0.2.4-beta] - 2025-12-11


Added

  • Uppy.js Image Upload Integration:
  • Migrated `/images/upload` page to use Uppy.js for modern, drag-and-drop file uploads.
  • Supports RAW image formats (TIF, TIFF, NEF, ARW) with maximum file size of 500MB.
  • Integrated with centralized `ImageUploadHelper` for system-wide upload configuration.
  • Maintains "Link to Photo Request" functionality with metadata handling.
  • Responsive design with theme integration and centered upload area.
  • Enhanced error handling with proper JSON response parsing (strips PHP warnings).
  • Server-side validation for `request_id` to prevent foreign key constraint violations.

  • Image Format Helper:
  • Created `ImageFormatHelper` class to centralize format-related utilities.
  • Provides `getMimeTypeForFormat()` for consistent MIME type mapping across controllers.
  • Added `normalizeFormat()` for format identifier normalization (e.g., 'jpeg' -> 'jpg').
  • Added `isSupportedFormat()` for format validation.
  • Eliminates code duplication between `ImageController` and `NasController`.

  • Source Format Badge with Conversion Settings Tooltip:
  • Added source format badge on image detail pages (`/images/:id`) showing original format (e.g., "Source: TIFF").
  • Badge displays with distinctive blue-gray color to differentiate from format badges.
  • Tooltip on hover shows comprehensive conversion settings from database:
  • Conversion format, max dimension, quality settings
  • Compression method, lossless mode, ICC profile preservation
  • Metadata preservation, speed settings, processing time
  • Uses Tippy.js with HTML content support for formatted tooltip display.

Changed

  • PHPDoc Documentation Updates:
  • Added comprehensive PHPDoc to `ImageController::upload()` method covering process flow, parameters, return values, and exceptions.
  • Added detailed PHPDoc to `ImageController::serveConverted()` explaining TIFF-to-AVIF conversion for browser compatibility.
  • Added PHPDoc to `ImageController::downloadConverted()` explaining file extension preservation.
  • Added comprehensive PHPDoc to `NasController::import()` covering batch import process, parameters, and return structure.
  • All PHPDoc blocks now include `@param`, `@return`, and `@throws` annotations where appropriate.

  • Code Refactoring:
  • Refactored duplicate `getMimeTypeForFormat()` methods in `ImageController` and `NasController` to use shared `ImageFormatHelper`.
  • Private methods in controllers now delegate to helper (marked as deprecated for backward compatibility).
  • Improved code maintainability and reduced duplication.

[0.2.3-beta] - 2025-12-11


Changed

  • Image Rating System UI:
  • Replaced star symbols (★, ☆, ⯨) with Material Google icons (`brightness_1`) for a more modern look.
  • Applied custom color `#75FB4C` to filled rating icons for better visual consistency.
  • Made rating display more compact: removed large prominent rating number, converted to inline layout with compact spacing.
  • Reduced icon sizes from 1.25rem to 0.9rem for a more subtle appearance.
  • Aligned rating circles to start at the same horizontal position regardless of label length.

  • Comments Section UI:
  • Made comments section more compact and less prominent: reduced title size, padding, and spacing throughout.
  • Reduced textarea from 3 rows to 2 rows with smaller padding and font size.
  • Made "Post Comment" button smaller with reduced padding and font size.
  • Reduced comment item padding and spacing for a more compact layout.
  • Reduced "no comments" message padding and font size.

  • Card Spacing:
  • Added consistent bottom margin (`margin-bottom: 1rem`) to all sidebar cards to prevent them from sticking together:
  • Rating card
  • Comments card
  • Workflow card
  • Downloads card
  • Upload Shop Version card
  • Metadata card
  • Workflow History card

  • Tooltip System Customization:
  • Customized Tippy.js tooltips with unique branding: solid purple color (`#667eea` in light mode, `#7c8ef0` in dark mode) instead of default styling.
  • Implemented smooth `shift-away` animation with cubic-bezier easing for professional appearance.
  • Added custom tooltip theme (`viewme-tooltip`) with rounded corners, shadow effects, and proper arrow styling.
  • Animation only transitions transform and opacity (no color transitions) for clean, consistent appearance.
  • All tooltips across the application now use the custom theme automatically.

[0.2.2-beta] - 2025-12-10


Added

  • Admin Settings Refactoring:
  • Refactored `/admin/settings` section for better organization and maintainability.
  • Phase 1 - Controller Split: Separated functionality into dedicated controllers:
  • `SystemMaintenanceController` for backup and data clearing operations
  • `CatalogController` for catalog import and preview functionality
  • `PdfTemplateController` for PDF template management
  • `SettingsController` now focuses only on core settings management
  • Phase 2 - View Components: Extracted view components for better organization:
  • Separated JavaScript into `public/assets/js/admin-settings.js`
  • Separated CSS into `public/assets/css/admin-settings.css`
  • Created individual tab partials in `app/Views/admin/settings/tabs/` (datetime, image, printer, permissions, catalog, pdf_templates, frontend, system_admin, companies)
  • Created `components/modals.php` for consolidated modal definitions
  • Phase 3 - Service Layer: Created `SystemInfoService` to extract system information gathering logic (database version, VIPS version, ImageMagick version) from controller, improving separation of concerns and testability.

  • Company Management System:
  • Added new "Companies" tab to `/admin/settings` for managing company profiles and addresses.
  • Created database schema for `companies` and `company_addresses` tables with UUID primary keys.
  • Supports flexible legal identifiers via JSON field (UID for Switzerland, HRB for Germany, EIN for USA, etc.).
  • One-to-Many address relationship: companies can have multiple addresses (billing, shipping, headquarters, registered office).
  • Full CRUD operations for companies and addresses via AJAX.
  • Company logo upload support: square and wide logo formats with file upload functionality.
  • Supported image formats: PNG, SVG, WebP, and AVIF (modern efficient formats).
  • Logo files stored in `public/uploads/companies/` directory.
  • Logo preview and management with delete functionality.
  • Company list display with logo thumbnails.
  • Form validation and error handling.
  • Uses ModalHelper system for consistent modal experience.
  • Responsive design: tabs wrap to multiple rows when needed, optimized for mobile/tablet.

  • SystemInfoService:
  • Created new service class (`app/Services/SystemInfoService.php`) for system information gathering.
  • Provides methods for database type/version detection, VIPS version detection, and ImageMagick version detection.
  • Reusable service that can be used across the application.

Changed

  • Admin Settings Layout:
  • Tabs now wrap to multiple rows when needed to accommodate all 9 tabs (datetime, image, printer, permissions, catalog, pdf_templates, frontend, system_admin, companies).
  • Reduced tab button padding slightly (from 1rem 1.5rem to 0.875rem 1.25rem) for better space utilization.
  • Improved tab border handling for multi-row layout.
  • Enhanced responsive behavior for mobile devices.

  • SettingsController:
  • Reduced from 158 lines to 95 lines (40% reduction) by extracting system info logic to service.
  • Cleaner, more focused controller following Single Responsibility Principle.

Fixed

  • Fixed missing closing `</div>` tag in catalog tab that was causing subsequent tabs (PDF Templates, Frontend, System Administration) to display incorrectly.

[Unreleased] - 2025-12-09


Added

  • User Management:
  • Added tabbed interface to `/admin/users` page with "Users" and "Roles" tabs, similar to settings page.
  • Implemented user badge color management: Users can have custom badge colors that override their role's default color.
  • Added color uniqueness validation: Each color can only be used by one role or user at a time.
  • Added inline toggle for user active/inactive status with AJAX updates (no page reload required).
  • Added "Unselect" functionality to clear badge colors for users.
  • Updated Badge helper to support user-specific badge colors that override role colors.
  • Added `badge_color` column to `users` table.

  • Roles Management:
  • Implemented role badge color management: Roles can now have custom badge colors from 10 predefined distinctive colors.
  • Added color uniqueness validation: Each color can only be used by one role or user at a time.
  • Added "Unselect" functionality to clear badge colors for roles.
  • Added `badge_color` column to `roles` table.
  • Created `Role` model for role management with color validation.
  • Added role CRUD operations: create, update, and delete roles via AJAX.
  • Color selection UI with visual indicators showing which colors are available vs. used.
  • Added protection for protected role names: Cannot change role names that are hardcoded in system configuration (prevents breaking access control).
  • Created `RoleHelper` for role management utilities and access control functions.

  • Permission & Access Control System:
  • Added helper functions `hasPermission($resource, $action)` and `hasRole($roles)` for easy permission checks in views.
  • Created comprehensive permission guide (`Docs/PERMISSION-GUIDE.md`) with usage examples and best practices.

  • Frontend Display Settings:
  • Added "Frontend" tab in `/admin/settings` for controlling what is displayed on the frontend.
  • Settings are only visible to administrators (admin-only access).
  • Frontend Debug Mode (Admin Only): Toggle setting (`frontend.debug_mode`) that controls debug output on frontend.
  • When enabled, displays debug panel on pages showing: current user information, permission checks, button visibility status, and code examples.
  • Helper function `isFrontendToggleEnabled()` for checking if debug mode is enabled.
  • Debug panel automatically shows current user permissions and which buttons are visible/hidden.
  • Created debug mode documentation (`Docs/DEBUG-MODE-GUIDE.md`) with implementation instructions.
  • Setting can be toggled via AJAX with automatic save functionality.

  • Shooting PDF Export & Print Functionality:
  • Implemented comprehensive PDF generation for shootings using mPDF library.
  • Added print modal on shooting view page with options for "PDF Export" and "Direct Print" (browser print).
  • Created `ShootingPdfGenerator` helper class for PDF generation with template-based rendering.
  • Added `shooting_print` PDF template type to admin settings with multi-language support (DE, FR, IT, EN).
  • PDF includes all shooting data: title, fancy name, date/time, status badge, location details (name, address, type, contact info, notes), description, requisites.
  • Models section: displays model information with primary images, contact details, hourly rates, parent/guardian info, and notes.
  • Requests/Products section: includes all request fields with status and priority badges, request details, instructions, model requirements, packaging requirements, catalog, reference images (attachments), request images, and remarks.
  • Bucket list: displayed on first page with visual indicators for completed items.
  • Conditional field display: only shows fields that contain data (no empty labels).
  • Badge rendering: status and priority badges are rendered with proper colors matching web interface.
  • Automatic language detection: PDF template language is automatically selected based on user's language preference.
  • Image support: includes model primary images, request images, and reference/inspiration images (multiple attachments supported).
  • "Open Shooting" display: shows "Open Shooting" instead of date when shooting has no scheduled date.
  • Template management: PDF templates can be edited and customized in `/admin/settings` under "PDF Templates" tab.
  • Route: `/shootings/:id/pdf` endpoint for PDF generation and download.
  • Template script: `add_shooting_print_template.php` for creating/updating shooting print templates.

  • Version & Changelog Display:
  • Version number in footer (Version 0.2.0-beta) is now clickable and displays changelog in a modal.
  • Changelog is automatically loaded from `Docs/changelog.md` and rendered with markdown parsing.
  • Modal displays formatted changelog with proper headers, lists, and styling.
  • Updated version from 0.1.0-alpha to 0.2.0-beta to reflect significant improvements and beta testing phase.

  • Modal Helper System:
  • Created centralized `Modal` helper class (`app/Helpers/Modal.php`) for consistent modal implementation across the application.
  • Supports multiple modal types: simple modals, form modals, and custom content modals.
  • Flexible size options: preset sizes (small: 400px, medium: 600px, large: 800px, xl: 1200px) or custom CSS values.
  • Built-in CSS and JavaScript rendering: `Modal::renderCSS()` and `Modal::renderJS()` provide all necessary styles and functionality.
  • JavaScript `ModalHelper` object with `open()`, `close()`, and `toggle()` methods for modal control.
  • Automatic features: closes on outside click, closes on Escape key, prevents body scroll when open.
  • Form modal support: optional form wrapping with configurable action, method, and form ID.
  • Customizable close functions: each modal can specify its own close function name.
  • Used across 9+ view files for consistent modal experience (shootings, models, images, requests, graphics, admin, dashboard).
  • Backward compatibility: provides `openModal()` and `closeModal()` global function aliases.
  • Created migration report (`Docs/MODAL-HELPER-MIGRATION-REPORT.md`) documenting modal standardization effort.

Changed

  • Workflow Icons in Requests (`/requests`):
  • Updated workflow icons to better reflect request status and progress.
  • Visual status indicators: Green for completed stages, blue for current stage, gray with reduced opacity for future stages.
  • Icons represent workflow stages: Open (radio_button_unchecked), Shooting (photo_camera), Graphics (brush), Shop (web), Completed (check_circle).
  • Improved status detection: Icons now accurately reflect completion status for graphics, shooting, and shop stages.
  • Clickable icons: Each workflow icon links to the detailed workflow overview page for that request.
  • Enhanced visual feedback: Color coding and opacity changes provide clear visual indication of request progress through the workflow pipeline.
  • Fixed bug: Shooting stage icon now properly turns green when shooting is completed, even if request has moved to later stages.

  • Header Navigation Dropdown Menu:
  • Fixed admin panel settings dropdown menu closing too quickly when hovering.
  • Added 200ms delay before closing dropdown menus to improve usability.
  • Improved hover detection: menu stays open when moving mouse from toggle to menu items.
  • Enhanced pointer-events handling for better interaction reliability.

  • Mobile & Tablet Responsive Design:
  • Comprehensive responsive design implementation across all major pages for optimal mobile and tablet user experience.
  • Admin Users Page (`/admin/users`): Converted table layout to card-based layout on mobile. Tables now stack vertically with labels, full-width action buttons, and optimized spacing. Tablet view provides horizontal scrolling.
  • Models Index Page (`/models`): Optimized filter toolbar to stack vertically on mobile, reduced grid card minimum size (150px on mobile), disabled hover effects on touch devices, optimized pagination and page header for mobile screens.
  • Models View Page (`/models/view/:id`): Converted 3-column grid to single column on mobile, stacked page header elements, made gallery actions always visible (not hover-only), optimized reference gallery for mobile, stacked detail rows for better readability. Tablet view uses 2-column layout.
  • Models Create/Edit Pages (`/models/create`, `/models/edit/:id`): Form layouts stack vertically on mobile with full-width inputs, optimized file upload areas, full-width action buttons, and better spacing for touch interaction.
  • Shootings Index Page (`/shootings`): Page header stacks vertically on mobile, calendar view optimized with stacked controls, FullCalendar toolbar adapted for mobile, shooting cards optimized with stacked meta information, improved stats section layout. View toggle buttons are full-width on mobile.
  • Shootings Create Page (`/shootings/create`): Form rows stack vertically on mobile, location selection buttons stack with full-width, search boxes optimized for mobile, all action buttons are full-width. Title field with fancy name display stacks properly.
  • Graphic Dashboard (`/graphic/dashboard`): Toolbar stacks vertically on mobile with full-width filters and view toggles, job cards optimized with stacked headers and actions, list view converts to card-based layout on mobile, image grids use smaller minimum sizes (150px on mobile). All buttons are full-width on mobile.
  • Shop Dashboard (`/shop/dashboard`): Toolbar and controls stack vertically on mobile, article groups optimized, version cards with full-width action buttons, list view converts to card-based layout on mobile, pagination stacks vertically. All interactive elements are touch-friendly.
  • Dashboard (`/dashboard`): Stats grid optimized for mobile (150px minimum), dashboard content stacks to single column, quick actions grid adapted for mobile, shooting items stack vertically, graphic jobs list optimized, activity list improved for mobile. All card headers stack vertically with full-width buttons.
  • Requests View Page (`/requests/view/:id`): Page header stacks with full-width action buttons, request details grid converts to single column, detail rows stack vertically, image grid optimized (100px minimum on mobile), rotation controls always visible on touch devices, workflow history timeline optimized, modals adapted for mobile screens. Upload modal tabs stack vertically on mobile.
  • All responsive changes maintain desktop functionality while providing improved mobile and tablet experiences.
  • Consistent responsive patterns applied across all pages: card-based layouts for tables, vertical stacking of form elements, full-width buttons on mobile, disabled hover effects on touch devices, optimized grid minimum sizes.
  • Touch-friendly interactions: All action buttons have adequate touch targets, hover-only features are disabled on touch devices, controls are always visible where needed.

  • Footer Spacing:
  • Fixed insufficient spacing between main content and footer.
  • Added `padding-bottom: 3rem` to `.main-content` and `padding-bottom: 2rem` to `.main-content .container` to create proper visual separation.
  • Improved overall page layout and visual hierarchy.

Fixed

  • Role Case Sensitivity:
  • Fixed "Permission denied" errors caused by case-sensitive role name comparisons (e.g., "Graphic" vs "graphic").
  • Normalized role names to lowercase at login and session read.
  • Updated all permission check functions to use case-insensitive role comparisons.
  • Modified `AuthController`, `BaseController`, `Permission` helper, `hasRole()` function, and `RoleHelper` to handle role names consistently.
  • Added `getRole()` helper method in `BaseController` for consistent role access.
  • Ensures all role comparisons work regardless of capitalization in database.

Security

  • Login Hardening:
  • Implemented brute-force protection: Accounts are locked for 15 minutes after 5 consecutive failed login attempts.
  • Added `failed_login_attempts` and `lockout_until` columns to the `users` table.
  • Implemented Session Fixation protection by regenerating session IDs upon successful login.
  • Added CSRF (Cross-Site Request Forgery) protection to the login form.
  • Enhanced session cookie security (HttpOnly, Secure, SameSite=Strict).
  • Activity Logging:
  • Added `ActivityLog` model to track login events (success, failure, lockout, inactive account access).

Infrastructure

  • Database Engine:
  • Removed SQLite Support: The system has been migrated to strictly support MySQL/MariaDB to handle growing data requirements.
  • Refactored `BaseModel` to remove SQLite connection logic.
  • Updated `Config.php` to remove SQLite parameters.
  • Refactored models and controllers (`ThumbnailQueue`, `Shooting`, `SettingsController`) to remove SQLite-specific conditional logic and use optimized MySQL queries (e.g., `FOR UPDATE`, `ON DUPLICATE KEY UPDATE`).
  • Updated background workers (`thumbnail_worker.php`, `catalog_import_worker.php`) to strictly use MySQL configuration.
  • Cleaned up system maintenance and index optimization scripts (`SystemMaintenance.php`, `optimize_models_indexes.php`, `optimize_shop_manager_indexes.php`, `optimize_images_indexes.php`) to rely on MySQL `information_schema`.
  • Removed legacy SQLite-specific migration scripts (`add_deleted_at_to_bucket_list.php`, `add_processed_by_to_image_versions.php`, `add_model_gender_column.php`).

Third-Party Software

PHP Dependencies

  • jcupitt/vips VIPS image processing library for high-performance image manipulation ↗ GitHub
  • claudiodekker/word-generator Word generator library (v1.6+) ↗ GitHub
  • mpdf/mpdf PHP library for generating PDF files from HTML (v8.2+) ↗ GitHub

JavaScript Libraries

  • jQuery JavaScript library for DOM manipulation and event handling ↗ Website
  • DataTables jQuery plugin for advanced tables with sorting, filtering, and pagination ↗ Website
  • Tippy.js Tooltip and popover library with customizable themes and animations ↗ Website
  • Popper.js Positioning engine for tooltips, popovers, and dropdowns (dependency of Tippy.js) ↗ Website
  • FullCalendar Full-featured calendar library for displaying events and scheduling (v6.1.10) ↗ Website
  • SortableJS JavaScript library for drag-and-drop reordering of list items ↗ Website

External Services

  • Google Material Icons Icon font library for Material Design icons (Material Icons Outlined) ↗ Website

Copyright & Legal

ViewMe

Copyright © 2025 ViewMe - Image Management System. All rights reserved.

ViewMe is an image management system designed for professional photography workflows.

Legal Information

This software is provided as-is for use in image management and photography workflows.

All content and images managed through this system remain the property of their respective owners. ViewMe does not claim ownership of any user-uploaded content.

For questions regarding copyright or legal matters, please contact your system administrator.