mirror of
https://github.com/khoaliber/LetterFeed.git
synced 2026-03-02 21:19:13 +00:00
feat: per newsletter folder move setting
This commit is contained in:
@@ -14,16 +14,26 @@ import { Plus } from "lucide-react"
|
||||
import { createNewsletter } from "@/lib/api"
|
||||
import { Checkbox } from "@/components/ui/checkbox"
|
||||
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from "@/components/ui/select"
|
||||
|
||||
interface AddNewsletterDialogProps {
|
||||
isOpen: boolean
|
||||
folderOptions: string[]
|
||||
onOpenChange: (isOpen: boolean) => void
|
||||
onSuccess: () => void
|
||||
}
|
||||
|
||||
export function AddNewsletterDialog({ isOpen, onOpenChange, onSuccess }: AddNewsletterDialogProps) {
|
||||
export function AddNewsletterDialog({ isOpen, folderOptions, onOpenChange, onSuccess }: AddNewsletterDialogProps) {
|
||||
const [newNewsletter, setNewNewsletter] = useState({
|
||||
name: "",
|
||||
emails: [""],
|
||||
move_to_folder: "",
|
||||
extract_content: false,
|
||||
})
|
||||
|
||||
@@ -54,9 +64,10 @@ export function AddNewsletterDialog({ isOpen, onOpenChange, onSuccess }: AddNews
|
||||
await createNewsletter({
|
||||
name: newNewsletter.name,
|
||||
sender_emails: newNewsletter.emails.filter((email) => email.trim()),
|
||||
move_to_folder: newNewsletter.move_to_folder,
|
||||
extract_content: newNewsletter.extract_content,
|
||||
})
|
||||
setNewNewsletter({ name: "", emails: [""], extract_content: false })
|
||||
setNewNewsletter({ name: "", emails: [""], move_to_folder: "", extract_content: false })
|
||||
onOpenChange(false)
|
||||
onSuccess()
|
||||
} catch (error) {
|
||||
@@ -83,6 +94,28 @@ export function AddNewsletterDialog({ isOpen, onOpenChange, onSuccess }: AddNews
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="move_to_folder">Move To Folder</Label>
|
||||
<Select
|
||||
value={newNewsletter.move_to_folder || "None"}
|
||||
onValueChange={(value) =>
|
||||
setNewNewsletter((prev) => ({ ...prev, move_to_folder: value === "None" ? "" : value }))
|
||||
}
|
||||
>
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder="Select folder or leave empty" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="None">Default (use global setting)</SelectItem>
|
||||
{folderOptions.map((folder) => (
|
||||
<SelectItem key={folder} value={folder}>
|
||||
{folder}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
|
||||
<div className="space-y-2">
|
||||
<Label>Email Addresses</Label>
|
||||
{newNewsletter.emails.map((email, index) => (
|
||||
|
||||
@@ -14,17 +14,27 @@ import { Plus } from "lucide-react"
|
||||
import { Newsletter, updateNewsletter, deleteNewsletter } from "@/lib/api"
|
||||
import { Checkbox } from "@/components/ui/checkbox"
|
||||
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from "@/components/ui/select"
|
||||
|
||||
interface EditNewsletterDialogProps {
|
||||
newsletter: Newsletter | null
|
||||
isOpen: boolean
|
||||
folderOptions: string[]
|
||||
onOpenChange: (isOpen: boolean) => void
|
||||
onSuccess: () => void
|
||||
}
|
||||
|
||||
export function EditNewsletterDialog({ newsletter, isOpen, onOpenChange, onSuccess }: EditNewsletterDialogProps) {
|
||||
const [editedDetails, setEditedDetails] = useState<{ name: string; emails: string[], extract_content: boolean }>({
|
||||
export function EditNewsletterDialog({ newsletter, isOpen, folderOptions, onOpenChange, onSuccess }: EditNewsletterDialogProps) {
|
||||
const [editedDetails, setEditedDetails] = useState<{ name: string; emails: string[], move_to_folder: string | null, extract_content: boolean }>({
|
||||
name: "",
|
||||
emails: [],
|
||||
move_to_folder: "",
|
||||
extract_content: false,
|
||||
})
|
||||
|
||||
@@ -33,6 +43,7 @@ export function EditNewsletterDialog({ newsletter, isOpen, onOpenChange, onSucce
|
||||
setEditedDetails({
|
||||
name: newsletter.name,
|
||||
emails: newsletter.senders.map((s) => s.email),
|
||||
move_to_folder: newsletter.move_to_folder || "",
|
||||
extract_content: newsletter.extract_content,
|
||||
})
|
||||
}
|
||||
@@ -66,6 +77,7 @@ export function EditNewsletterDialog({ newsletter, isOpen, onOpenChange, onSucce
|
||||
await updateNewsletter(newsletter.id, {
|
||||
name: editedDetails.name,
|
||||
sender_emails: editedDetails.emails.filter((email) => email.trim()),
|
||||
move_to_folder: editedDetails.move_to_folder,
|
||||
extract_content: editedDetails.extract_content,
|
||||
})
|
||||
onOpenChange(false)
|
||||
@@ -103,6 +115,27 @@ export function EditNewsletterDialog({ newsletter, isOpen, onOpenChange, onSucce
|
||||
onChange={(e) => setEditedDetails((prev) => ({ ...prev, name: e.target.value }))}
|
||||
/>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="edit-move_to_folder">Move To Folder</Label>
|
||||
<Select
|
||||
value={editedDetails.move_to_folder || "None"}
|
||||
onValueChange={(value) =>
|
||||
setEditedDetails((prev) => ({ ...prev, move_to_folder: value === "None" ? "" : value }))
|
||||
}
|
||||
>
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder="Select folder or leave empty" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="None">Default (use global setting)</SelectItem>
|
||||
{folderOptions.map((folder) => (
|
||||
<SelectItem key={folder} value={folder}>
|
||||
{folder}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<Label>Email Addresses</Label>
|
||||
{editedDetails.emails.map((email, index) => (
|
||||
|
||||
@@ -30,7 +30,7 @@ describe("AddNewsletterDialog", () => {
|
||||
entries_count: 0,
|
||||
})
|
||||
|
||||
render(<AddNewsletterDialog isOpen={true} onOpenChange={handleOpenChange} onSuccess={handleSuccess} />)
|
||||
render(<AddNewsletterDialog isOpen={true} folderOptions={["INBOX", "Archive"]} onOpenChange={handleOpenChange} onSuccess={handleSuccess} />)
|
||||
|
||||
// Fill out the form
|
||||
fireEvent.change(screen.getByLabelText(/Newsletter Name/i), { target: { value: "My New Newsletter" } })
|
||||
@@ -44,6 +44,7 @@ describe("AddNewsletterDialog", () => {
|
||||
expect(mockedApi.createNewsletter).toHaveBeenCalledWith({
|
||||
name: "My New Newsletter",
|
||||
sender_emails: ["test@example.com"],
|
||||
move_to_folder: "",
|
||||
extract_content: false,
|
||||
})
|
||||
expect(handleSuccess).toHaveBeenCalledTimes(1)
|
||||
@@ -52,7 +53,7 @@ describe("AddNewsletterDialog", () => {
|
||||
})
|
||||
|
||||
it("allows adding and removing email fields", () => {
|
||||
render(<AddNewsletterDialog isOpen={true} onOpenChange={() => {}} onSuccess={() => {}} />)
|
||||
render(<AddNewsletterDialog isOpen={true} folderOptions={[]} onOpenChange={() => {}} onSuccess={() => {}} />)
|
||||
|
||||
// Initial state
|
||||
expect(screen.getAllByPlaceholderText(/Enter email address/i)).toHaveLength(1)
|
||||
@@ -67,7 +68,7 @@ describe("AddNewsletterDialog", () => {
|
||||
})
|
||||
|
||||
it("closes the dialog when cancel is clicked", () => {
|
||||
render(<AddNewsletterDialog isOpen={true} onOpenChange={handleOpenChange} onSuccess={handleSuccess} />)
|
||||
render(<AddNewsletterDialog isOpen={true} folderOptions={["INBOX", "Archive"]} onOpenChange={handleOpenChange} onSuccess={handleSuccess} />)
|
||||
|
||||
fireEvent.click(screen.getByRole("button", { name: /Cancel/i }))
|
||||
expect(handleOpenChange).toHaveBeenCalledWith(false)
|
||||
|
||||
@@ -18,6 +18,7 @@ const mockNewsletter: Newsletter = {
|
||||
id: 1,
|
||||
name: "Existing Newsletter",
|
||||
is_active: true,
|
||||
extract_content: false,
|
||||
senders: [{ id: 1, email: "current@example.com", newsletter_id: 1 }],
|
||||
entries_count: 5,
|
||||
}
|
||||
@@ -39,6 +40,7 @@ describe("EditNewsletterDialog", () => {
|
||||
<EditNewsletterDialog
|
||||
newsletter={mockNewsletter}
|
||||
isOpen={true}
|
||||
folderOptions={["INBOX", "Archive"]}
|
||||
onOpenChange={handleOpenChange}
|
||||
onSuccess={handleSuccess}
|
||||
/>
|
||||
@@ -59,6 +61,8 @@ describe("EditNewsletterDialog", () => {
|
||||
expect(mockedApi.updateNewsletter).toHaveBeenCalledWith(1, {
|
||||
name: "Updated Name",
|
||||
sender_emails: ["current@example.com"],
|
||||
move_to_folder: "",
|
||||
extract_content: false,
|
||||
})
|
||||
expect(handleSuccess).toHaveBeenCalledTimes(1)
|
||||
expect(handleOpenChange).toHaveBeenCalledWith(false)
|
||||
@@ -72,6 +76,7 @@ describe("EditNewsletterDialog", () => {
|
||||
<EditNewsletterDialog
|
||||
newsletter={mockNewsletter}
|
||||
isOpen={true}
|
||||
folderOptions={["INBOX", "Archive"]}
|
||||
onOpenChange={handleOpenChange}
|
||||
onSuccess={handleSuccess}
|
||||
/>
|
||||
@@ -95,6 +100,7 @@ describe("EditNewsletterDialog", () => {
|
||||
<EditNewsletterDialog
|
||||
newsletter={mockNewsletter}
|
||||
isOpen={true}
|
||||
folderOptions={["INBOX", "Archive"]}
|
||||
onOpenChange={handleOpenChange}
|
||||
onSuccess={handleSuccess}
|
||||
/>
|
||||
|
||||
Reference in New Issue
Block a user