Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
100 commits
Select commit Hold shift + click to select a range
099c1d9
Updated design guide
Developing-Gamer Dec 4, 2025
5ed00b2
Emails page fixed (1 of 4)
Developing-Gamer Dec 5, 2025
c4ebbdf
Email Drafts page redesigned ( 2 of 4)
Developing-Gamer Dec 5, 2025
0f7cd52
Merge branch 'dev' into emails-redesign
Developing-Gamer Dec 25, 2025
269d0d6
Merge branch 'dev' into emails-redesign
Developing-Gamer Dec 26, 2025
d3ef4b1
Merge errors resolved, delete drafts option implemented, upgrade to p…
Developing-Gamer Dec 25, 2025
c1a4bbf
Sidebar visual bugs fixed
Developing-Gamer Dec 26, 2025
35fe2d4
Fixed stack companion support icon
Developing-Gamer Dec 26, 2025
fe5817f
Made the previews responsive, added option to delete custom themes
Developing-Gamer Dec 26, 2025
28c1f29
updated email templates page design
Developing-Gamer Dec 26, 2025
10bbd91
Merge branch 'dev' into emails-redesign
Developing-Gamer Dec 29, 2025
e704733
Merge branch 'dev' into emails-redesign
Developing-Gamer Dec 31, 2025
98a4d15
Merge branch 'dev' into emails-redesign
Developing-Gamer Jan 2, 2026
c401251
Better template editor layout (not good enough tho)
Developing-Gamer Dec 29, 2025
f5ce638
Fixed Push #2
Developing-Gamer Jan 3, 2026
76257b0
Code reviewer bot suggestions implemented
Developing-Gamer Jan 3, 2026
9fbcec1
Refactor email template deletion logic and enhance error handling in …
Developing-Gamer Jan 3, 2026
a3aec0d
Enhance email template deletion process with improved error handling …
Developing-Gamer Jan 3, 2026
f202c2f
Update DataTable components to improve sorting and visibility handlin…
Developing-Gamer Jan 7, 2026
069c6e8
Enhance GlassCard component in emails themes page with improved hover…
Developing-Gamer Jan 7, 2026
af0a49d
Refactor AI chat message validation and error handling in route.tsx. …
Developing-Gamer Jan 7, 2026
8552ff4
Suggestions implemented
Developing-Gamer Jan 7, 2026
0d98993
Merge branch 'dev' into emails-redesign
Developing-Gamer Jan 7, 2026
10586f6
remaining suggestions implemented
Developing-Gamer Jan 7, 2026
245b231
Enhance sidebar layout with gradual blur on vertical edges. Updated g…
Developing-Gamer Jan 8, 2026
f788c5d
Merge branch 'dev' into emails-redesign
Developing-Gamer Jan 8, 2026
474780d
Merge branch 'dev' into emails-redesign
Developing-Gamer Jan 9, 2026
dc6ff53
Merge branch 'dev' into emails-redesign
Developing-Gamer Jan 10, 2026
6202689
Merge branch 'dev' into emails-redesign
Developing-Gamer Jan 12, 2026
c12ccfb
Sidebar tooltip fixed
Developing-Gamer Jan 12, 2026
61c8c32
Design Components Page
Developing-Gamer Jan 12, 2026
86c46fa
Merge remote-tracking branch 'origin/dev' into emails-redesign
N2D4 Jan 13, 2026
4d935a5
Various small changes
N2D4 Jan 14, 2026
80d73fe
WYSIWYG editor for email editor (#1104)
N2D4 Jan 14, 2026
cce6396
Refactor design language page and enhance component structure
Developing-Gamer Jan 20, 2026
c019472
Enhance design language page with dropdown menu features
Developing-Gamer Jan 20, 2026
7c5a35f
Selector menu
Developing-Gamer Jan 20, 2026
fba2248
Implement data table for email log in design language page
Developing-Gamer Jan 20, 2026
0a8a073
Enhance design language page with new input and editable grid components
Developing-Gamer Jan 20, 2026
9ae5ad7
remove quetzal codegen
N2D4 Jan 20, 2026
c03ed40
Updated and Fixed Component Library
Developing-Gamer Jan 23, 2026
3f68b99
Merge remote-tracking branch 'origin/dev' into emails-redesign
Developing-Gamer Jan 23, 2026
ef148fc
Updated editable grid
Developing-Gamer Jan 23, 2026
14755bb
build error fix attemp 1
Developing-Gamer Jan 24, 2026
8f55afc
Merge branch 'dev' into emails-redesign
Developing-Gamer Jan 24, 2026
330b106
build fixes
Developing-Gamer Jan 24, 2026
d31894c
Refactor email rendering and AI chat components for improved error ha…
Developing-Gamer Jan 30, 2026
66c6912
Final Fixes (Design Complete, Tests Done, Features working)
Developing-Gamer Jan 31, 2026
d5a2b15
review comment fixes
Developing-Gamer Jan 31, 2026
7917408
Merge remote-tracking branch 'origin/dev' into emails-redesign
N2D4 Feb 2, 2026
b5f1db9
Merge branch 'dev' into emails-redesign
Developing-Gamer Feb 5, 2026
1144a9d
backend deployment error fixed
Developing-Gamer Feb 5, 2026
f778487
Merge branch 'dev' into emails-redesign
Developing-Gamer Feb 5, 2026
bf4e9ac
Review comments addressed:
Developing-Gamer Feb 5, 2026
56e2a99
Merge remote-tracking branch 'origin/dev' into emails-redesign
N2D4 Feb 10, 2026
a75c931
Small fixes
N2D4 Feb 11, 2026
a128128
Merge branch 'dev' into emails-redesign
Developing-Gamer Feb 11, 2026
bc68f95
Merge branch 'dev' into emails-redesign
Developing-Gamer Feb 11, 2026
faef712
Refactor email draft handlers to simplify error handling. Replace try…
Developing-Gamer Feb 11, 2026
a5fb6aa
Lightmode (#1168)
Developing-Gamer Feb 11, 2026
ae0bb2b
Update sidebar-layout styles for improved responsiveness in main cont…
Developing-Gamer Feb 11, 2026
c9c0074
Editors visible now
Developing-Gamer Feb 11, 2026
c9a9968
Enhance UI components with off-white light mode support and improve l…
Developing-Gamer Feb 11, 2026
e3b1c88
Add CursorBlastEffect component to LayoutClient and remove from PageC…
Developing-Gamer Feb 11, 2026
d7872cb
Refactor design components to unify imports under `design-components`…
Developing-Gamer Feb 11, 2026
9befb84
Merge branch 'dev' into emails-redesign
Developing-Gamer Feb 11, 2026
6565f42
Enhance email draft and theme components with off-white light mode su…
Developing-Gamer Feb 11, 2026
b872c46
Merge remote-tracking branch 'origin/dev' into emails-redesign
N2D4 Feb 12, 2026
eb9e15d
Update EditableGrid component
N2D4 Feb 12, 2026
5184c11
Merge branch 'dev' into emails-redesign
Developing-Gamer Feb 13, 2026
86837f9
Refactor SidebarLayout component for improved styling and layout cons…
Developing-Gamer Feb 13, 2026
0208c21
fix: test snapshot updates
nams1570 Feb 13, 2026
f2076e2
Replaced with Design Components in Overview Pages
Developing-Gamer Feb 13, 2026
841185f
Onboarding app
Developing-Gamer Feb 14, 2026
b643e48
Enhance DesignDataTable with glassmorphic and toolbar options. Update…
Developing-Gamer Feb 16, 2026
7f49d2b
Team Settings
Developing-Gamer Feb 16, 2026
54d00e8
Project Permissions
Developing-Gamer Feb 16, 2026
1250432
API Keys Page
Developing-Gamer Feb 16, 2026
1c16e69
Data Vault
Developing-Gamer Feb 16, 2026
db42568
webhooks page
Developing-Gamer Feb 16, 2026
a3bc181
Launch Checklist page
Developing-Gamer Feb 16, 2026
1295380
Vercel Integration page
Developing-Gamer Feb 16, 2026
e1e7929
Replaced components in explore apps but didn't redesign
Developing-Gamer Feb 16, 2026
aca2f60
Project Keys Page
Developing-Gamer Feb 16, 2026
999c272
Project Settings Page
Developing-Gamer Feb 16, 2026
6f7553a
Merge branch 'dev' into update-dashboard-components
Developing-Gamer Feb 16, 2026
a309168
Merge branch 'dev' into update-dashboard-components
Developing-Gamer Feb 16, 2026
0268140
Enhance email template handling and improve UI components
Developing-Gamer Feb 16, 2026
c4d68dd
Refactor project settings and webhooks components
Developing-Gamer Feb 17, 2026
bf7bcc2
Enhance project settings and webhooks functionality
Developing-Gamer Feb 17, 2026
6e96981
Comment undo
Developing-Gamer Mar 2, 2026
5fa6a91
Chart Layout in smaller screens bug fixed
Developing-Gamer Mar 2, 2026
b8c0e46
fix: adjust height calculation for vertical blur layer in sidebar layout
Developing-Gamer Mar 2, 2026
e2fdaa6
Merge branch 'dev' into update-dashboard-components
Developing-Gamer Mar 2, 2026
01f9809
refactor: remove unused imports and optimize column memoization in AP…
Developing-Gamer Mar 2, 2026
fc9075a
Merge branch 'dev' into update-dashboard-components
Developing-Gamer Mar 2, 2026
6ab92e0
Merge branch 'dev' into update-dashboard-components
Developing-Gamer Mar 5, 2026
2cfdd15
Merge branch 'dev' into update-dashboard-components
Developing-Gamer Mar 9, 2026
516e3b1
Merge branch 'dev' into update-dashboard-components
Developing-Gamer Mar 9, 2026
9e38775
Merge branch 'dev' into update-dashboard-components
Developing-Gamer Mar 10, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Refactor email template deletion logic and enhance error handling in …
…email logs. Updated sender email formatting to exclude non-alphanumeric characters. Added tests for email template deletion scenarios, including handling of shared email configurations.
  • Loading branch information
Developing-Gamer committed Jan 3, 2026
commit 9fbcec10fbdf3987b289afd69daa0afe6b29e406
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,9 @@ export default function PageClient() {
const [deleteDialogOpen, setDeleteDialogOpen] = useState<string | null>(null);

const handleDelete = async (templateId: string) => {
try {
await stackAdminApp.deleteEmailTemplate(templateId);
toast({ title: "Template deleted successfully", variant: "success" });
setDeleteDialogOpen(null);
} catch (error) {
toast({ title: "Failed to delete template", variant: "destructive" });
}
await stackAdminApp.deleteEmailTemplate(templateId);
toast({ title: "Template deleted successfully", variant: "success" });
setDeleteDialogOpen(null);
};
Comment thread
coderabbitai[bot] marked this conversation as resolved.

return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,7 @@ export default function PageClient() {
viewport={selectedViewport}
emailSubject="Verify your email address"
senderName={project.displayName}
senderEmail={`noreply@${project.displayName.toLowerCase().replace(/\s+/g, '')}.com`}
senderEmail={`noreply@${project.displayName.toLowerCase().replace(/[^a-z0-9]/g, '')}.com`}
/>
</div>
</GlassCard>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -233,16 +233,20 @@ function EmailLogCard() {
const stackAdminApp = useAdminApp();
const [emailLogs, setEmailLogs] = useState<AdminSentEmail[]>([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
const tableRef = useRef<TableType<AdminSentEmail> | null>(null);
const [, forceUpdate] = useState({});

// Fetch email logs when component mounts
useEffect(() => {
runAsynchronously(async () => {
setLoading(true);
setError(null);
try {
const emails = await stackAdminApp.listSentEmails();
setEmailLogs(emails);
} catch (err) {
setError(err instanceof Error ? err.message : "Failed to load email logs");
} finally {
setLoading(false);
}
Expand Down Expand Up @@ -272,6 +276,32 @@ function EmailLogCard() {
);
}

if (error) {
return (
<GlassCard gradientColor="slate" className="overflow-hidden">
<div className="p-5">
<SectionHeader icon={Envelope} title="Email Log" />
<Typography variant="secondary" className="text-sm mt-1">
View and manage email sending history
</Typography>
</div>
<div className="border-t border-foreground/[0.05] flex items-center justify-center py-12">
<div className="flex flex-col items-center gap-3 text-center max-w-sm">
<div className="p-3 rounded-xl bg-destructive/10">
<Envelope className="h-5 w-5 text-destructive" />
</div>
<div className="space-y-1">
<Typography className="text-sm font-medium text-foreground">Failed to load emails</Typography>
<Typography variant="secondary" className="text-sm">
{error}
</Typography>
</div>
</div>
</div>
</GlassCard>
);
}

if (emailLogs.length === 0) {
return (
<GlassCard gradientColor="slate" className="overflow-hidden">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ it("should allow adding and updating email templates with custom email config",
expect(updateResponse).toMatchInlineSnapshot(`
NiceResponse {
"status": 200,
"body": { "rendered_html": "<!DOCTYPE html PUBLIC \\"-//W3C//DTD XHTML 1.0 Transitional//EN\\" \\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\\"><html dir=\\"ltr\\" lang=\\"en\\"><head><meta content=\\"text/html; charset=UTF-8\\" http-equiv=\\"Content-Type\\"/><meta name=\\"x-apple-disable-message-reformatting\\"/></head><body style=\\"background-color:rgb(250,251,251);font-family:ui-sans-serif, system-ui, sans-serif, &quot;Apple Color Emoji&quot;, &quot;Segoe UI Emoji&quot;, &quot;Segoe UI Symbol&quot;, &quot;Noto Color Emoji&quot;;font-size:1rem;line-height:1.5rem;margin:0px;padding:0px;overflow-x:hidden\\"><!--$--><div style=\\"padding-top:2rem;padding-bottom:2rem;padding-left:1rem;padding-right:1rem;display:flex;justify-content:center\\"><table align=\\"center\\" width=\\"100%\\" border=\\"0\\" cellPadding=\\"0\\" cellSpacing=\\"0\\" role=\\"presentation\\" style=\\"background-color:rgb(255,255,255);padding:45px;border-radius:0.5rem;box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), 0 0 #0000;margin-left:auto;margin-right:auto;max-width:600px;width:100%\\"><tbody><tr style=\\"width:100%\\"><td><div>Mock email template</div></td></tr></tbody></table></div><table align=\\"center\\" width=\\"100%\\" border=\\"0\\" cellPadding=\\"0\\" cellSpacing=\\"0\\" role=\\"presentation\\" style=\\"padding:1rem;opacity:0.6;text-align:center\\"><tbody><tr><td><span style=\\"color:rgb(37,99,235)\\">Click here</span> to unsubscribe from these emails</td></tr></tbody></table><!--7--><!--/$--></body></html>" },
"body": { "rendered_html": "<!DOCTYPE html PUBLIC \\"-//W3C//DTD XHTML 1.0 Transitional//EN\\" \\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\\"><html dir=\\"ltr\\" lang=\\"en\\"><head><meta content=\\"text/html; charset=UTF-8\\" http-equiv=\\"Content-Type\\"/><meta name=\\"x-apple-disable-message-reformatting\\"/></head><body style=\\"background-color:rgb(250,251,251);font-family:ui-sans-serif, system-ui, sans-serif, &quot;Apple Color Emoji&quot;, &quot;Segoe UI Emoji&quot;, &quot;Segoe UI Symbol&quot;, &quot;Noto Color Emoji&quot;;font-size:1rem;line-height:1.5rem;margin:0px;padding:0px;overflow-x:hidden\\"><!--$--><div style=\\"padding-top:2rem;padding-bottom:2rem;padding-left:1rem;padding-right:1rem;display:flex;justify-content:center\\"><table align=\\"center\\" width=\\"100%\\" border=\\"0\\" cellPadding=\\"0\\" cellSpacing=\\"0\\" role=\\"presentation\\" style=\\"background-color:rgb(255,255,255);padding:45px;border-radius:0.5rem;box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), 0 0 #0000;margin-left:auto;margin-right:auto;max-width:600px;width:100%\\"><tbody><tr style=\\"width:100%\\"><td><div>Mock email template</div></td></tr></tbody></table></div><table align=\\"center\\" width=\\"100%\\" border=\\"0\\" cellPadding=\\"0\\" cellSpacing=\\"0\\" role=\\"presentation\\" style=\\"padding:1rem;opacity:0.6;text-align:center\\"><tbody><tr><td><a href=\\"https://example.com\\" target=\\"_blank\\" rel=\\"noopener noreferrer\\" style=\\"color:rgb(37,99,235)\\">Click here</a> to unsubscribe from these emails</td></tr></tbody></table><!--7--><!--/$--></body></html>" },
"headers": Headers { <some fields may have been hidden> },
}
`);
Expand Down Expand Up @@ -134,3 +134,119 @@ it("should create a new email template and be able to retrieve it", async ({ exp
expect(createdTemplate).toBeDefined();
expect(createdTemplate.display_name).toBe("Test Template");
});

it("should not allow deleting email templates when using shared email config", async ({ expect }) => {
// Create a project with shared email config (default)
await Auth.fastSignUp();
const { adminAccessToken } = await Project.createAndGetAdminToken();

// Try to delete an email template
const response = await niceBackendFetch("/api/v1/internal/email-templates/a70fb3a4-56c1-4e42-af25-49d25603abd0", { // EMAIL_TEMPLATE_PASSWORD_RESET_ID
method: "DELETE",
accessType: "admin",
headers: {
'x-stack-admin-access-token': adminAccessToken,
},
});

// Verify that the delete was rejected
expect(response).toMatchInlineSnapshot(`
NiceResponse {
"status": 400,
"body": {
"code": "REQUIRES_CUSTOM_EMAIL_SERVER",
"error": "This action requires a custom SMTP server. Please edit your email server configuration and try again.",
},
"headers": Headers {
"x-stack-known-error": "REQUIRES_CUSTOM_EMAIL_SERVER",
<some fields may have been hidden>,
},
}
`);
});

it("should successfully delete an email template with custom email config", async ({ expect }) => {
// Create a project with custom email config
await Auth.fastSignUp();
await Project.createAndSwitch({
config: {
email_config: {
type: 'standard',
host: 'smtp.example.com',
port: 587,
username: 'test@example.com',
password: 'password123',
sender_name: 'Test App',
sender_email: 'noreply@example.com'
}
}
});

// Create a new template to delete
const createResponse = await niceBackendFetch("/api/v1/internal/email-templates", {
method: "POST",
accessType: "admin",
body: {
display_name: "Template to Delete",
},
});

expect(createResponse.status).toBe(200);
const templateId = createResponse.body.id;

// Verify the template exists
const listBeforeDelete = await niceBackendFetch("/api/v1/internal/email-templates", {
method: "GET",
accessType: "admin",
});

const templateBeforeDelete = listBeforeDelete.body.templates.find((t: any) => t.id === templateId);
expect(templateBeforeDelete).toBeDefined();

// Delete the template
const deleteResponse = await niceBackendFetch(`/api/v1/internal/email-templates/${templateId}`, {
method: "DELETE",
accessType: "admin",
});

expect(deleteResponse.status).toBe(200);
expect(deleteResponse.body).toEqual({});

// Verify the template is removed from the list
const listAfterDelete = await niceBackendFetch("/api/v1/internal/email-templates", {
method: "GET",
accessType: "admin",
});

const templateAfterDelete = listAfterDelete.body.templates.find((t: any) => t.id === templateId);
expect(templateAfterDelete).toBeUndefined();
});

it("should return NotFound when deleting a non-existent template", async ({ expect }) => {
// Create a project with custom email config
await Auth.fastSignUp();
await Project.createAndSwitch({
config: {
email_config: {
type: 'standard',
host: 'smtp.example.com',
port: 587,
username: 'test@example.com',
password: 'password123',
sender_name: 'Test App',
sender_email: 'noreply@example.com'
}
}
});

// Try to delete a non-existent template with a valid UUID format
const nonExistentTemplateId = "00000000-0000-0000-0000-000000000000";
const deleteResponse = await niceBackendFetch(`/api/v1/internal/email-templates/${nonExistentTemplateId}`, {
method: "DELETE",
accessType: "admin",
});

// Verify that we get a 404 NotFound error
expect(deleteResponse.status).toBe(404);
expect(deleteResponse.body).toContain("No template found with given id");
});
Loading