Commit d22f629
* feat(google-workspace): add Google Drive integration (OAuth + Picker)
Free feature, always on. Lets each user connect their own Google account
and attach Drive files to tasks by reference (drive.file scope).
- OAuth2 connect/disconnect via WP HTTP API (no SDK); per-user tokens
encrypted at rest (AES-256-CBC, key from WP salts), auto-refresh.
- Admin sets site-level OAuth credentials + Picker keys (Client ID/Secret,
API key, App ID). Settings_Page_Access gated.
- Google Picker (client-side) for browsing under least-privilege drive.file;
setOrigin + z-index/pointer-events handling for in-admin embedding.
- Task detail "Google Drive" section: attach/list/detach file references.
- DB tables wp_pm_google_tokens, wp_pm_google_drive_files (idempotent install
+ last_used_at self-heal).
- 60-day stale-token purge via daily cron.
- uninstall.php removes Google Workspace tables/options/cron only.
- Graceful reconnect when site salts rotate (undecryptable tokens purged).
- Browser guidance for third-party-cookie blocking (Chrome/Brave/Safari).
Files: src/Google_Workspace/* (Loader, Google_Client, Google_Service,
Models, Controllers), routes/google-workspace.php, React store slice +
components/google-workspace/*, registrations in index.jsx, sidebar nav,
TaskDetailSheet picker-aware outside-close guard, Create_Table + start.php
bootstrap, uninstall.php.
* refactor(google-workspace): split admin setup from per-user connection
- Move site-level OAuth credentials into Settings → Google Workspace tab
(new GoogleWorkspaceSettingsTab; admin-only via the Settings page gate).
- Google Workspace page is now per-user account connection only
(connect/disconnect/status) + a features overview (Drive available;
Calendar/Meet coming soon) so future features slot in cleanly.
- One account connection powers all Google Workspace features.
- Sidebar nav uses the Google Drive logo instead of the disk icon.
No backend changes; reuses existing settings/status/auth endpoints.
* style(google-workspace): monochrome nav/settings logo; sidebar label Google Drive (free) / Google Workspace (pro)
* feat(google-workspace): admin toggle to enable/disable Google Drive (hidden everywhere when off)
* style(google-workspace): literal G Drive/G Workspace labels + outlined nav icons
* style(google-workspace): refine monochrome Drive nav/settings glyph
* style(google-workspace): adopt 2026 Drive icon — monochrome in nav/settings, full color in task/connection
* style(google-workspace): outline the 2026 Drive icon in nav/settings
* feat(google-workspace): per-project Drive role access + move G Workspace settings tab to top
* feat(google-workspace): clearer 'View only' message in task Drive section when role can't attach
* fix(google-workspace): strict role gating on frontend (show Attach only when allowed) + enforce detach permission
* fix(google-workspace): no Connect prompt / hide section for roles without Drive access (admin + frontend)
* refactor(google-workspace): polymorphic attachments (task/comment/discussion/project) + shared GoogleDriveAttach component
* feat(google-workspace): attach Drive files to task comments (+ orphan cleanup on comment/task delete)
* fix(google-workspace): comment Drive attach restricted to comment author or manager (UI + API)
* style(google-workspace): section button label 'Attach'; compact comment button = + with mono Drive icon
* feat(google-workspace): Drive attach in discussions (body + comments) + discussion orphan cleanup
* feat(google-workspace): attach Drive files while creating a discussion (staged, attached on create)
* feat(google-workspace): expose Drive components via window.PM for pro
* feat(google-workspace): allow 'file' attachable type for Drive attachments
* feat(google-workspace): clamp list to 2 + Show all; adder avatar; outlined hover-reveal comment button
* fix(google-workspace): comment Drive button reveal via opacity (was hidden + ungenerated variant)
* feat(google-workspace): comment Drive add as icon-only button beside edit/delete (order: drive, edit, delete); chips render below via showAdd=false
* feat(google-workspace): show 'Google Drive' label only in task section; discussion/file headers show icon + count only
* feat(google-workspace): drop comment Drive chips; icon button beside edit/delete is the only comment surface
* feat(google-workspace): add Pro extension slots + upgrade covers for Calendar & Meet
- G Workspace page: Calendar/Meet rows are now Slots (google.workspace.feature.{calendar,meet}); free shows a clickable Pro upgrade teaser, Pro fills them.
- Settings tab: Calendar sync + Meet groups shown as locked Pro teasers (google.workspace.settings.{calendar,meet} slots) behind the upgrade modal.
- Drive remains the free feature; Calendar/Meet reserved for Pro.
* feat(google-workspace): incremental Calendar-scope consent infra (free)
- Google_Client: add CALENDAR_SCOPE; get_auth_url() accepts a scope override.
- OAuth_Controller: auth-url honors with_calendar (requests calendar.events alongside drive.file via include_granted_scopes); status returns calendar_connected.
- Google_Service: user_has_scope()/user_has_calendar(); Loader localizes calendar_connected.
- Slice getAuthUrl({withCalendar}); expose GW thunks (fetchStatus/getAuthUrl/disconnect) on window.PM for Pro.
* feat(google-workspace): move Calendar config to the sidebar G Workspace page
- Calendar is now a card section on the G Workspace page (slot google.workspace.feature.calendar), Pro fills it with sync settings + connect; free shows a Pro cover card.
- Drop the Calendar/Meet teasers from the admin settings tab (creds-only again).
* feat(google-workspace): Workspace page = per-feature connection cards; sidebar label 'Google Workspace' (free+pro)
- Sidebar nav label unified to 'Google Workspace' for free and pro.
- Workspace page now shows Connected services cards: Google Drive (free, status) + Calendar/Meet slots (Pro connect cards, free covers).
- Calendar config (enable + sync options) moved back to Settings -> Google Workspace (admin) via the settings.calendar slot.
* feat(google-workspace): per-user service prefs on Workspace page
- Drive card gets a per-user on/off (user meta pm_gws_drive_on); user_can_use_drive respects it; status/localize expose drive_user_on; new POST google-workspace/my-prefs; saveDrivePref thunk.
* feat(google-workspace): note that all features use one account; reconnecting a different account replaces it
* feat(google-workspace): fire pm_google_before_disconnect (token still valid) for feature cleanup
* feat(google-workspace): disconnect confirm modal (plugin AlertDialog, wider) explaining consequences
* feat(google-workspace): G Workspace sidebar label; smaller settings desc + setup docs link; admin toggle to disable Drive in comments (auto-save+toast, enforced UI+API); branded Calendar/Meet icons in free teasers
* fix(google-workspace): use plugin ProBadge for teasers; neutral calendar connect prompt; docs link icon-only top-right
* fix(google-workspace): settings tab — G Workspace heading, shorter desc, credentials heading, icon-less feature toggles; trim account note 2nd line
* fix(google-workspace): settings — Google glyph + 'Google Workspace' heading, larger credentials heading, grouped Drive enable + Drive-in-comments card with Drive logo
* fix(google-workspace): settings header glyph violet (plugin accent), not multicolor Google
* fix(google-workspace): settings header glyph inline + w-5 (match Pusher); remove Drive icon from Enable Google Drive toggle
* feat(google-workspace): incremental Meet scope (meetings.space.created) + meet_connected status; getAuthUrl supports withMeet
* fix(google-workspace): reset calendar/meet connected state on disconnect
* fix(google-workspace): Drive toggle off when account disconnected
* feat(google-workspace): comment.composer.action slot in task + discussion comment composers
* fix(comment): guard null parent_comment/commentable in activity logging (was fatal -> 500 on add comment)
* fix(google-workspace): show Drive attachments under task + discussion comments (was attached but not rendered)
* feat(google-workspace): unified Drive+Meet link insertion in comment composers (new + edit); drop chips + per-comment attach button (CommentLinkActions)
* fix(google-workspace): drop emoji from inserted Drive link (4-byte emoji broke save on utf8mb3 comment column)
* feat(google-workspace): icon-only Drive/Meet composer buttons; add Meeting to discussion create form
* feat(google-workspace): unify Drive icon in discussion create (CommentLinkActions); allowMeet flag
* fix(google-workspace): normalize sidebar Drive nav glyph size/centering (viewBox padding) to align with label
* revert: sidebar Drive nav glyph viewBox back to 0 0 24 24 (no resize)
* fix(google-workspace): top-align sidebar Google icon with the label (no resize)
* style(google-meet): update Meet brand icon (colored places); monochrome composer unchanged
* feat(google-workspace): log Drive attach/detach + Meet activity, monochrome marks in activity feeds
* feat(google-workspace): decorate Drive/Meet links in comment view (file-type icons + Meet card); expose decorateGoogleLinks on window.PM
* copy(google-workspace): use 'team members' wording in Drive comments setting
* chore(google-workspace): remove dead Meet scope chain (MEET_SCOPE/user_has_meet/with_meet) — Meet uses calendar.events
* security(google-workspace): prevent injected markup in comment link rendering — DOM-build Meet card with textContent, escape + http(s)-validate inserted Drive/Meet links
* fix(google-workspace): add G Workspace to admin submenu under Sprints; sidebar any-feature gate + reactive; active-route highlight for /google-workspace
* fix(google-workspace): enforce Drive master toggle on usage + Drive card off-state; align access route perms to Project_Settings_Page_Access; localize calendar/meet master flags; drop dead Meet scope
* fix(drive): bind Drive attachments to the route project (IDOR)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* harden(google): safe token-key fallback + gate picker_config to Drive-enabled
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* refactor(google): consolidate inline Google/Drive/Meet SVGs into GoogleIcons.jsx
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* feat(google): hide Drive/Meet comment links from members without project access
Google links pasted into comments were shown to every project member. Now the
comment transformer runs content through a wedevs_pm_comment_content_visibility
filter; Google_Workspace strips Drive/Docs/Meet anchors (replacing them with
plain text) when the requesting user fails the existing per-project role
permission Google_Service::user_can_use_drive() — managers/admins pass,
co_worker/client gated by the project access map. Stripped server-side so the
URL never reaches the response. No-op unless the content actually holds a
google.com link.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix(uninstall): preserve user data — stop dropping tables/options on delete
uninstall.php dropped pm_google_tokens + pm_google_drive_files and deleted the
settings options, destroying user data on plugin delete/reinstall (this is the
free wp.org core plugin). Now it only clears the scheduled cleanup cron; no
tables dropped, no options deleted.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: anik-fahmid <fahmid.cse.cou@gmail.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent c0ac273 commit d22f629
38 files changed
Lines changed: 2999 additions & 24 deletions
File tree
- bootstrap
- core/WP
- db
- routes
- src
- Activity/Transformers
- Comment
- Observers
- Transformers
- Google_Workspace
- Controllers
- Models
- views/assets/src
- components
- admin-settings
- tabs
- google-workspace
- layout
- projects
- ActivitiesPage
- parts
- DiscussionsPage
- tasks
- TaskDetailSheet
- lib
- store
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
22 | 22 | | |
23 | 23 | | |
24 | 24 | | |
| 25 | + | |
25 | 26 | | |
26 | 27 | | |
27 | 28 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
37 | 37 | | |
38 | 38 | | |
39 | 39 | | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
40 | 70 | | |
41 | 71 | | |
42 | 72 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
26 | 26 | | |
27 | 27 | | |
28 | 28 | | |
| 29 | + | |
29 | 30 | | |
30 | 31 | | |
31 | 32 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
152 | 152 | | |
153 | 153 | | |
154 | 154 | | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
155 | 159 | | |
156 | 160 | | |
157 | 161 | | |
| |||
228 | 232 | | |
229 | 233 | | |
230 | 234 | | |
| 235 | + | |
| 236 | + | |
| 237 | + | |
| 238 | + | |
| 239 | + | |
| 240 | + | |
| 241 | + | |
| 242 | + | |
| 243 | + | |
| 244 | + | |
231 | 245 | | |
232 | 246 | | |
233 | 247 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
37 | 37 | | |
38 | 38 | | |
39 | 39 | | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
40 | 43 | | |
41 | 44 | | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
42 | 48 | | |
43 | 49 | | |
44 | 50 | | |
| |||
67 | 73 | | |
68 | 74 | | |
69 | 75 | | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
70 | 85 | | |
71 | 86 | | |
72 | 87 | | |
73 | 88 | | |
74 | 89 | | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
75 | 94 | | |
76 | 95 | | |
77 | 96 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
30 | 30 | | |
31 | 31 | | |
32 | 32 | | |
33 | | - | |
| 33 | + | |
34 | 34 | | |
35 | 35 | | |
36 | 36 | | |
| |||
0 commit comments