Feat/work session tracker#3385
Conversation
Agent-Logs-Url: https://github.com/intelli-verse-x/leantime/sessions/5e0887a2-5ff8-4d2a-9f2d-153343a79aa0 Co-authored-by: Anisid930 <249399046+Anisid930@users.noreply.github.com>
…ject convention Agent-Logs-Url: https://github.com/intelli-verse-x/leantime/sessions/5e0887a2-5ff8-4d2a-9f2d-153343a79aa0 Co-authored-by: Anisid930 <249399046+Anisid930@users.noreply.github.com>
…fix HTMX swap bug Agent-Logs-Url: https://github.com/intelli-verse-x/leantime/sessions/6502c86b-763f-4561-b768-b1c0488f43f1 Co-authored-by: Anisid930 <249399046+Anisid930@users.noreply.github.com>
…ct self-1:1s Agent-Logs-Url: https://github.com/intelli-verse-x/leantime/sessions/5743d506-7a1e-47d0-bad3-806ae094d3e8 Co-authored-by: Anisid930 <249399046+Anisid930@users.noreply.github.com>
…architecture feat(oneonone): Weekly 1:1 Employee Sheet — manage every team member's 1:1s
Agent-Logs-Url: https://github.com/intelli-verse-x/leantime/sessions/6387661f-5c1c-4483-8d71-c0d5af85a97b Co-authored-by: Anisid930 <249399046+Anisid930@users.noreply.github.com>
Agent-Logs-Url: https://github.com/intelli-verse-x/leantime/sessions/6387661f-5c1c-4483-8d71-c0d5af85a97b Co-authored-by: Anisid930 <249399046+Anisid930@users.noreply.github.com>
Agent-Logs-Url: https://github.com/intelli-verse-x/leantime/sessions/0108f721-c4fb-4782-a791-0e51dad252fc Co-authored-by: Anisid930 <249399046+Anisid930@users.noreply.github.com>
Agent-Logs-Url: https://github.com/intelli-verse-x/leantime/sessions/261700ca-2817-4754-9b0f-f255375211d8 Co-authored-by: Anisid930 <249399046+Anisid930@users.noreply.github.com>
Agent-Logs-Url: https://github.com/intelli-verse-x/leantime/sessions/261700ca-2817-4754-9b0f-f255375211d8 Co-authored-by: Anisid930 <249399046+Anisid930@users.noreply.github.com>
Agent-Logs-Url: https://github.com/intelli-verse-x/leantime/sessions/261700ca-2817-4754-9b0f-f255375211d8 Co-authored-by: Anisid930 <249399046+Anisid930@users.noreply.github.com>
Agent-Logs-Url: https://github.com/intelli-verse-x/leantime/sessions/261700ca-2817-4754-9b0f-f255375211d8 Co-authored-by: Anisid930 <249399046+Anisid930@users.noreply.github.com>
Agent-Logs-Url: https://github.com/intelli-verse-x/leantime/sessions/261700ca-2817-4754-9b0f-f255375211d8 Co-authored-by: Anisid930 <249399046+Anisid930@users.noreply.github.com>
…etup-and-roles Fix invite email delivery by hardening fallback sender address generation
- Add role 25 teamlead between editor and manager; en-US label - Oneonone: team leads use same flows as managers for team sessions; menu Management submenu for teamlead; auth arrays include teamlead - showTeam: safe initials when names missing - Mailer.sendMail returns bool; sendUserInvite/createUserInvite surface mail failures - NewUser, EditUser resend, InviteTeamStep: notifications on mail failure vs success Co-authored-by: Cursor <cursoragent@cursor.com>
Phase 1 - Navigation & language: - Add LEAN_SIMPLE_WORKFLOW config (DefaultConfig + sample.env) - Rename menu labels: Todos→Tasks, Milestones→Timeline, Blueprints→Planning, Current Project→Active Project - Filter 'advanced' submenu (canvas/strategy/retros/wiki) when simpleWorkflow=true - Add Workflow.MD planning document Phase 2 - My Work dashboard: - Remove milestone re-injection from My ToDos widget (only tasks shown) - Add empty state with quick-add when no tasks exist (emptyState component) - Add inline quick-add form per group in myToDos widget - Show 'Assigned by' on task rows when assigned by a different user Auth & role fixes: - Fix userHasRole() to use hierarchical numeric comparison for array roles so Team Lead (25) passes checks that allow editor (20) and above - Make onboarding task input optional (removed required attr + empty guard) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Expose MySQL on host port 3307 to avoid Laragon conflict - Add --ignore-platform-req for ext-pcntl and ext-posix so composer install works on Windows without those extensions - Remove restrictive Tailwind classes from blocklist to allow more utility classes in templates Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Team Lead role (value 25) added between Editor and Manager - managerId column on zp_user for manager assignment - Simple Workflow toggle in company settings (hides advanced menus) - Menu label renames (Tasks, Timeline, Files, Planning, etc.) - New dashboard widgets: Recently Updated, Waiting on Me - WeeklyPlanning domain: full weekly plan CRUD, team view, blockers, commitments, feedback exchange, carry-over, history - Role and permission checks updated throughout - Language keys added/updated (en-US.ini) - Ignore memory/ directory (Claude Code local memory, not for repo) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add .gitattributes enforcing LF across the project to prevent false modified status on Windows due to CRLF/LF mismatch.
Leantime's Frontcontroller uses Str::studly() to convert URL segments
to class names. 'weeklyplanning' studly-cases to 'Weeklyplanning', not
'WeeklyPlanning', causing a 404 on all weekly planning pages.
Renamed all URL slugs from /weeklyplanning/ to /weekly-planning/ so
Str::studly('weekly-planning') correctly resolves to 'WeeklyPlanning'.
Updated menu module keys and section type mappings to match.
- Implemented `countOpenRequests` method in ClientPortal service to count open client requests. - Created `AdminHome` controller for the admin dashboard, displaying project cards with overdue and blocked task counts. - Added new admin dashboard template with KPI strip for active projects, overdue tasks, blocked tasks, and open client requests. - Updated menu repository to include admin dashboard and related routes for admin users. - Restricted access to project retrieval in Projects service for non-admin roles. - Updated head menu to display current admin route title for admin users. - Removed project type column from project listing for cleaner UI. - Added new language entries for admin menu items.
…I consistency - Added WeeklyPlanningService to MyToDos for filtering out tickets already in the current week's plan. - Updated RecentlyUpdated and WaitingOnMe controllers for consistent variable formatting. - Refactored myToDos.blade.php for improved readability and consistency in HTML structure. - Introduced new language strings for milestone management and notifications. - Enhanced sidebar toggle functionality in app layout for better user experience. - Added Dashboard for Team Leads/Company Managers.
…Configuration - Removed the Tasks controller, consolidating task management logic. - Updated Notepad repository method to improve date handling for recent tasks. - Simplified Tailwind CSS configuration by removing unused theme settings and adjusting content paths. - Disabled preflight in Tailwind to prevent conflicts with Bootstrap styles.
- Updated widget URLs in the Widgets.php file for consistency. - Improved code formatting in moveableWidget.blade.php, calendar.blade.php, myToDos.blade.php, and todoItem.blade.php for better readability. - Ensured proper indentation and spacing throughout the affected files. - Added missing newlines at the end of several files to adhere to coding standards.
This reverts commit d90de2a.
- Implemented MyToDosCalendar HTMX controller to display user's personal calendar with tasks and events. - Created MyToDosKanban HTMX controller to show tickets assigned to the user, grouped by status. - Developed MyToDosRecentlyUpdated HTMX controller to list recently updated tasks for the user. - Updated Widgets service to include new My Todos widgets and adjusted grid dimensions. - Enhanced myToDos template to support view toggling between List, Kanban, Calendar, and Recently Updated. - Added new Blade templates for MyToDosCalendar, MyToDosKanban, and MyToDosRecentlyUpdated.
…le for back to users button
…to team leads and above
- Updated user role checks in various templates and controllers to include a second parameter for global role validation. - Ensured that team leads can perform actions regardless of their project-specific roles. - Adjusted the layout and styling of the main content area to improve readability on large screens. - Added missing font entries to the mix-manifest for proper loading of font assets.
- Updated ticket detail templates to allow users to attach either files or links as references, with appropriate UI changes and JavaScript functionality to toggle between options. - Improved ticket management for plans by adding similar reference attachment functionality. - Implemented ownership checks in the DelTime controller to restrict deletion of time entries to their owners or authorized roles. - Adjusted ShowMy controller to restrict time logging for developers to tickets they are assigned to or collaborate on. - Added modal functionality for deleting time entries in the timesheets JavaScript controller. - Enhanced user management by introducing co-manager functionality in user creation and editing processes, including database updates and UI changes. - Updated language files to include new labels for attachment options and co-manager fields. - Made CSS adjustments for better layout and readability in the main content area.
|
|
There was a problem hiding this comment.
Pull request overview
This PR introduces two new functional domains—(1) a Work Session Tracker with screenshot capture and monitoring, and (2) a Weekly 1:1 (“Oneonone”) module—alongside supporting role/menu changes and some operational/deployment additions. It also improves user-invitation flows by surfacing whether invitation emails were successfully handed off to the mailer.
Changes:
- Add a Worktracker module (REST API + HTMX navbar timer + employee/admin dashboards) with screenshot persistence/streaming.
- Add a Oneonone module (team dashboard, session detail page, HTMX live item editing) and introduce a new
teamleadrole plus menu entries. - Improve invite-email feedback by making the mailer/send-invite path return success/failure; add Docker/buildspec + dispatch deploy workflow.
Reviewed changes
Copilot reviewed 44 out of 46 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| tailwind.config.js | Tailwind config adjustments (but currently includes a critical unexpected payload). |
| Dockerfile | Builds an image layered on leantime/leantime:3.7.3 by copying app/ and public/. |
| buildspec.yml | CodeBuild steps to build/push image to ECR and roll out to EKS. |
| app/Language/en-US.ini | Adds new notification strings, role label, and Oneonone UI strings. |
| app/Domain/Worktracker/Templates/showDashboard.blade.php | Employee “My Work Sessions” dashboard + start/stop/cancel UX and screenshot capture JS. |
| app/Domain/Worktracker/Templates/showAdmin.blade.php | Admin monitor table for all sessions with pagination. |
| app/Domain/Worktracker/Templates/partials/timer.blade.php | Navbar timer widget with HTMX polling + start/stop JS. |
| app/Domain/Worktracker/Services/WorkTracker.php | Work session lifecycle logic, screenshot validation/storage, dashboard aggregations. |
| app/Domain/Worktracker/Repositories/WorkTracker.php | DB access for work sessions (currently also performs runtime schema creation). |
| app/Domain/Worktracker/PRIVACY.md | Employee-facing privacy notice for the Work Session Tracker feature. |
| app/Domain/Worktracker/Hxcontrollers/Timer.php | HTMX controller for navbar timer widget status refresh. |
| app/Domain/Worktracker/Controllers/ShowDashboard.php | Controller assembling employee dashboard view model. |
| app/Domain/Worktracker/Controllers/ShowAdmin.php | Controller assembling admin monitor view model (admin/owner gated). |
| app/Domain/Worktracker/Controllers/Screenshot.php | Auth-gated screenshot streaming endpoint. |
| app/Domain/Api/Controllers/Worktracker.php | REST API for starting/stopping/cancelling sessions and reading status. |
| app/Domain/Users/Services/Users.php | Invite flow now reports whether mail send succeeded. |
| app/Domain/Users/Controllers/NewUser.php | Shows distinct notifications for user creation vs invite-email delivery. |
| app/Domain/Users/Controllers/EditUser.php | Resend-invite UI now reports email send success/failure. |
| app/Domain/Oneonone/Templates/showTeam.blade.php | Manager/team dashboard view for 1:1s. |
| app/Domain/Oneonone/Templates/showSession.blade.php | 1:1 session detail view with editable meta + HTMX item list. |
| app/Domain/Oneonone/Templates/showMy.blade.php | Employee “My 1:1s” timeline and open action items panel. |
| app/Domain/Oneonone/Templates/partials/sessionItem.blade.php | HTMX-enabled session item row rendering. |
| app/Domain/Oneonone/Templates/partials/sessionCard.blade.php | Reusable session “card” rendering for lists/timelines. |
| app/Domain/Oneonone/Templates/partials/myOpenActions.blade.php | Auto-refreshing open action items panel for current user. |
| app/Domain/Oneonone/Templates/partials/itemList.blade.php | Grouped item list per type with HTMX add-item form. |
| app/Domain/Oneonone/Templates/newSession.blade.php | “Schedule 1:1” form. |
| app/Domain/Oneonone/Templates/delSession.blade.php | Delete confirmation view for a 1:1 session. |
| app/Domain/Oneonone/Services/Oneonone.php | Oneonone business logic: permissions, session CRUD, item CRUD, dashboards. |
| app/Domain/Oneonone/Repositories/Oneonone.php | Oneonone DB access for sessions/items + query helpers. |
| app/Domain/Oneonone/Models/Session.php | Data model for 1:1 sessions. |
| app/Domain/Oneonone/Models/SessionItem.php | Data model for 1:1 session items. |
| app/Domain/Oneonone/Hxcontrollers/SessionItems.php | HTMX controller for add/toggle/update/delete/list items + my open actions. |
| app/Domain/Oneonone/Controllers/ShowTeam.php | Controller for team dashboard + scheduling entry. |
| app/Domain/Oneonone/Controllers/ShowSession.php | Controller for session detail GET/POST updates. |
| app/Domain/Oneonone/Controllers/ShowMy.php | Controller for employee “My 1:1s” + stats. |
| app/Domain/Oneonone/Controllers/NewSession.php | Controller for scheduling a new session. |
| app/Domain/Oneonone/Controllers/DelSession.php | Controller for deleting a session. |
| app/Domain/Menu/Templates/headMenu.blade.php | Injects the Worktracker timer widget into the global head menu. |
| app/Domain/Menu/Repositories/Menu.php | Adds Oneonone menu items; adjusts Management submenu role threshold. |
| app/Domain/Install/Services/SchemaBuilder.php | Adds schema creation for Oneonone and Work sessions on fresh installs. |
| app/Domain/Install/Repositories/Install.php | Adds DB update 30502 to create Oneonone tables for upgrades. |
| app/Domain/Help/Services/InviteTeamStep.php | Shows mail-delivery warning when invites fail to send. |
| app/Domain/Auth/Models/Roles.php | Adds teamlead role and numeric role mapping. |
| app/Core/Mailer.php | Normalizes default from-domain and returns boolean success from sendMail(). |
| app/Core/Configuration/AppSettings.php | Bumps DB version from 3.5.1 → 3.5.2. |
| .gitignore | Adds additional ignore patterns (e.g., config.bat, node_modules). |
| .github/workflows/dispatch-deploy.yml | Workflow to dispatch a downstream build/deploy in another repo on master pushes. |
Comments suppressed due to low confidence (1)
app/Domain/Oneonone/Templates/showTeam.blade.php:87
- This second occurrence also references the missing translation key "text.oneonone.no_date". Please add the key to the language file or use an existing date-missing label so the UI doesn't render the untranslated key string.
@if (!empty($member['nextSession']['meetingDate']))
{{ dtHelper()->parseDbDateTime($member['nextSession']['meetingDate'])->setToUserTimezone()->format(__('language.dateformat')) }}
@else
{{ __('text.oneonone.no_date') }}
@endif
</a>
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| Auth::authOrRedirect([Roles::$editor, Roles::$manager, Roles::$admin, Roles::$owner], true); | ||
|
|
||
| $sessionId = isset($_GET['session_id']) ? (int) $_GET['session_id'] : 0; | ||
| $type = $_GET['type'] ?? ''; | ||
|
|
||
| if ($sessionId <= 0 || ! in_array($type, ['start', 'end'], true)) { | ||
| return new Response('Bad request', 400); | ||
| } | ||
|
|
||
| $currentUserId = (int) session('userdata.id'); | ||
| $currentRole = session('userdata.role') ?? ''; | ||
| $isPrivileged = in_array($currentRole, [Roles::$manager, Roles::$admin, Roles::$owner], true); | ||
|
|
| public function __construct(DbCore $db) | ||
| { | ||
| $this->db = $db->getConnection(); | ||
| $this->ensureTableExists(); | ||
| } |
| @php | ||
| $wtStatus = session()->exists('userdata') | ||
| ? app(\Leantime\Domain\Worktracker\Services\WorkTracker::class) | ||
| ->getTimerStatus((int) session('userdata.id')) | ||
| : ['running' => false]; | ||
| $wtFormatted = $wtStatus['running'] | ||
| ? \Leantime\Domain\Worktracker\Services\WorkTracker::formatDuration($wtStatus['elapsed_seconds']) | ||
| : '00:00:00'; | ||
| @endphp | ||
| @include('worktracker::partials.timer', [ | ||
| 'timerStatus' => $wtStatus, | ||
| 'formattedTime' => $wtFormatted, | ||
| ]) |
| - aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin 970547373533.dkr.ecr.us-east-1.amazonaws.com | ||
| - REPOSITORY_URI=970547373533.dkr.ecr.us-east-1.amazonaws.com/leantime | ||
| - COMMIT_HASH=$(echo $CODEBUILD_RESOLVED_SOURCE_VERSION | cut -c 1-7) | ||
| - IMAGE_TAG=$(if [ -n "$COMMIT_HASH" ]; then echo $COMMIT_HASH; else echo latest; fi) | ||
| - echo "Image tag is $IMAGE_TAG" |
| - echo "Deploying to EKS" | ||
| - aws eks update-kubeconfig --name ai-cart-auto-cluster --region us-east-1 --kubeconfig /root/.kube/config | ||
| - export KUBECONFIG=/root/.kube/config | ||
| - kubectl set image deployment/leantime leantime=$REPOSITORY_URI:$IMAGE_TAG -n aicart | ||
| - kubectl rollout status deploy/leantime -n aicart --timeout=300s |
| public function startSession(int $userId, string $base64Screenshot): array | ||
| { | ||
| // Prevent duplicate running sessions | ||
| $existing = $this->repo->getActiveSession($userId); | ||
| if ($existing !== false) { | ||
| return [ | ||
| 'success' => false, | ||
| 'session_id' => (int) $existing->id, | ||
| 'message' => 'A session is already running.', | ||
| ]; | ||
| } | ||
|
|
||
| $screenshotPath = ''; | ||
| if (! empty($base64Screenshot)) { |
| @if (!empty($member['lastSession']['meetingDate'])) | ||
| {{ dtHelper()->parseDbDateTime($member['lastSession']['meetingDate'])->setToUserTimezone()->format(__('language.dateformat')) }} | ||
| @else | ||
| {{ __('text.oneonone.no_date') }} | ||
| @endif | ||
| </a> |
Internal time-tracking + screenshot module for Leantime. Module surface -------------- - Start/Stop work session from a navbar widget (live ticker) - One start screenshot (required) and optional end screenshot via browser Screen Capture API (getDisplayMedia) — JPEG, max 1920x1080 - Employee dashboard (/worktracker/showDashboard) with today/week/total stats and full session history - Admin/Owner monitor (/worktracker/showAdmin) — managers see aggregate only, no direct screenshot access - Auth-gated screenshot serving with path-traversal protection - Orphan-session recovery: "Cancel (no screenshot)" closes hung sessions - Two stop flows: quick stop (navbar) and stop-with-screenshot (dashboard) Browser support gate -------------------- Client-side feature detection of navigator.mediaDevices.getDisplayMedia. Safari and mobile browsers see a clear "browser not supported" message up-front instead of confusing "permission denied" errors. Schema ------ SchemaBuilder creates zp_work_sessions on fresh install. Existing deployments already provisioned via standalone SQL migration. Privacy ------- PRIVACY.md (app/Domain/Worktracker/) — 1-page employee notice covering what is captured, when, who can see it, retention, and rights. CI/CD ----- .github/workflows/dispatch-deploy.yml fires repository_dispatch to intelli-verse-kube-infra on push to master, which rebuilds the leantime image and rolls it out. Requires GH_PAT_KUBE_INFRA secret.
Master push is already auto-built and rolled out by AWS CodePipeline (leantime-pipeline) via the existing root-level buildspec.yml — the GH-Actions dispatcher was duplicating that path.
a7d9ea9 to
9ce6ca8
Compare
Description
Please include a short description of the suggested change and the reasoning behind the approach you have chosen.
Link to ticket
Please add a link to the GitHub issue being addressed by this change.
Type
Screenshot of the result
If your change affects the user interface, you should include a screenshot of the result with the pull request.