Skip to content

feat(mail): attach files from Frappe Drive in the composer - #238

Draft
krantheman wants to merge 1 commit into
frappe:developfrom
krantheman:mail-attach-from-drive
Draft

feat(mail): attach files from Frappe Drive in the composer#238
krantheman wants to merge 1 commit into
frappe:developfrom
krantheman:mail-attach-from-drive

Conversation

@krantheman

Copy link
Copy Markdown
Member

Overview

Implements #46 — attach files from Frappe Drive while composing a mail.

The composer's paperclip becomes a small menu:

  • Upload from computer — the existing local upload, unchanged.
  • Attach from Frappe Drive — opens a Drive file picker.

What's included

  • DriveFilePicker.vue (new modal): browses the user's Drive — team home with breadcrumb folder navigation, folders-first listing, and multi-select — backed by suite.drive.api.list.files (+ permissions.get_teams). A team selector appears only for multi-team users.
  • ComposeMailToolbar.vue: the paperclip is now a Dropdown with the two attach options.
  • ComposeMailEditor.vue: on Drive selection, each file's bytes are fetched via suite.drive.api.files.get_file_content (permission-checked server-side), wrapped as a File, and pushed through the existing upload pipeline (upload_fileattachDoc). A Drive attachment therefore becomes an ordinary Frappe File with a real file_url, and the send path (create_mail/update_draft_mail) needs no changes.

Scope matches the maintainer's note on #46: Frappe Drive only (no Google Drive etc.).

Design note

The "copy bytes" approach (fetch from Drive → re-upload through mail's upload_file) was chosen over teaching the mail backend to resolve a Drive entity_name, because a Drive file's file_url is a storage key that the mail queue can't read directly — Drive always serves bytes through permission-checked get_file_content. Reusing the proven attachment pipeline keeps the change frontend-only.

Testing

Compose a mail → paperclip → Attach from Frappe Drive → browse/select one or more files → Attach. The files appear as normal attachments and send with the mail. Verified end-to-end locally: select → get_file_contentupload_file → attachment chip in the composer.

🤖 Generated with Claude Code

Adds a "Attach from Frappe Drive" entry to the composer's attach menu
(the paperclip is now a menu: Upload from computer / Attach from Frappe
Drive). A new DriveFilePicker modal browses the user's Drive — team home
with folder navigation and multi-select — backed by
suite.drive.api.list.files.

Selected files are fetched as bytes via suite.drive.api.files
.get_file_content (permission-checked server-side) and pushed through the
existing upload pipeline (mail.upload_file -> attachDoc), so a Drive
attachment becomes an ordinary Frappe File with a real file_url and the
send path is unchanged.

Closes frappe#46

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@krantheman
krantheman requested a review from s-aga-r as a code owner July 16, 2026 12:08
@greptile-apps

greptile-apps Bot commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Confidence Score: 4/5

Safe to merge after fixing the team-change selection leak; the rest of the change is additive and reuses proven upload logic.

Switching teams in the picker silently carries over file selections from the previous team, causing unintended attachments. Everything else — the toolbar dropdown, breadcrumb navigation, Promise.allSettled fetch loop — looks correct.

DriveFilePicker.vue — specifically the onTeamChange handler.

Reviews (1): Last reviewed commit: "feat(mail): attach files from Frappe Dri..." | Re-trigger Greptile

Comment on lines +205 to +208
const onTeamChange = () => {
breadcrumbs.value = [{ name: null, label: __('Home') }]
load()
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 onTeamChange resets the breadcrumbs and reloads the file list but never clears selected or selectedEntries. A user who selects files in Team A, switches to Team B, and clicks Attach silently re-attaches the Team A files — the counter still shows them and they are all emitted.

Suggested change
const onTeamChange = () => {
breadcrumbs.value = [{ name: null, label: __('Home') }]
load()
}
const onTeamChange = () => {
breadcrumbs.value = [{ name: null, label: __('Home') }]
selected.value = new Set()
selectedEntries.clear()
load()
}

@krantheman
krantheman marked this pull request as draft July 24, 2026 06:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant