blob: 56fd89a54e5f1d82f01ae3e72f3c6508f3d5b4bc (
plain)
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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
|
<div class="slide-up space-y-6 max-w-lg mx-auto pt-12">
<div class="glass rounded-xl glow-border">
<div class="px-5 py-4 border-b border-white/[0.04]">
<h2 class="text-sm font-medium text-zinc-200">Edit Mailbox</h2>
</div>
<div class="p-5">
{% url "mail.mailboxes.update" id=mailbox.ID as update_path %}
<form hx-put="{{ update_path }}" hx-swap="none" class="space-y-4">
<div>
<label class="block text-xs font-medium text-zinc-400 mb-1.5 ml-1">Address</label>
<input type="text" value="{{ mailbox.Address }}" disabled class="input-field opacity-50 cursor-not-allowed">
</div>
<div>
<label class="block text-xs font-medium text-zinc-400 mb-1.5 ml-1">Owner</label>
<div class="dropdown" data-dropdown>
<input type="hidden" name="user_id" value="{{ mailbox.UserID }}" data-dropdown-value>
<button type="button" class="input-field text-left flex items-center justify-between" data-dropdown-trigger>
<span class="truncate" data-dropdown-label>{{ mailbox.User.DisplayName }} ({{ mailbox.User.Username }})</span>
<svg class="w-4 h-4 text-zinc-500 shrink-0 ml-2 transition-transform duration-150" data-dropdown-chevron fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="1.5">
<path stroke-linecap="round" stroke-linejoin="round" d="m19.5 8.25-7.5 7.5-7.5-7.5" />
</svg>
</button>
<div class="dropdown-menu" data-dropdown-menu>
<div class="p-2 border-b border-white/[0.04]">
<input type="text" placeholder="Search users..." class="dropdown-search" data-dropdown-search>
</div>
<div class="dropdown-options" data-dropdown-options>
{% for user in users %}
<button type="button" class="dropdown-option" data-dropdown-option data-value="{{ user.ID }}" data-label="{{ user.DisplayName }} ({{ user.Username }})">
<div>
<p class="text-sm text-zinc-200">{{ user.DisplayName }}</p>
<p class="text-xs text-zinc-500">{{ user.Username }}</p>
</div>
</button>
{% endfor %}
</div>
<div class="dropdown-empty hidden" data-dropdown-empty>
<p class="text-xs text-zinc-500 text-center py-3">No users found</p>
</div>
</div>
</div>
</div>
<div class="flex items-center gap-3 pt-2">
<button type="submit" class="btn-primary">Save Changes</button>
{% url "mail.mailboxes" as mailboxes_path %}
<a href="{{ mailboxes_path }}" hx-get="{{ mailboxes_path }}" hx-target="#content" hx-swap="innerHTML" hx-push-url="true" class="text-xs text-zinc-500 hover:text-zinc-300 transition-colors duration-150">Cancel</a>
</div>
</form>
</div>
</div>
<div class="glass rounded-xl glow-border">
<div class="flex items-center justify-between px-5 py-4 border-b border-white/[0.04]">
<h2 class="text-sm font-medium text-zinc-200">Aliases</h2>
<span class="text-xs text-zinc-600">{{ aliases|length }} total</span>
</div>
{% if aliases %}
<div class="divide-y divide-white/[0.04]">
{% for alias in aliases %}
<div class="flex items-center justify-between px-5 py-3">
<div class="flex items-center gap-3">
<div class="flex items-center justify-center w-8 h-8 rounded-lg bg-purple-500/10">
<svg class="w-4 h-4 text-purple-400" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="1.5">
<path stroke-linecap="round" stroke-linejoin="round" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622 1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244" />
</svg>
</div>
<p class="text-sm text-zinc-200">{{ alias.SourceAddress }}</p>
</div>
{% url "mail.aliases.delete" id=mailbox.ID alias_id=alias.ID as delete_alias_path %}
<button data-confirm-trigger data-confirm-title="Delete {{ alias.SourceAddress }}" data-confirm-message="This alias will be permanently removed. Emails sent to this address will no longer be forwarded." data-confirm-action="{{ delete_alias_path }}" class="text-xs text-zinc-600 hover:text-red-400 transition-colors duration-150">Remove</button>
</div>
{% endfor %}
</div>
{% else %}
<div class="flex flex-col items-center justify-center py-8 text-center">
<p class="text-xs text-zinc-500">No aliases configured</p>
</div>
{% endif %}
<div class="px-5 py-4 border-t border-white/[0.04]">
{% url "mail.aliases.create" id=mailbox.ID as create_alias_path %}
<form hx-post="{{ create_alias_path }}" hx-swap="none" class="space-y-4">
<div>
<label class="block text-xs font-medium text-zinc-400 mb-1.5 ml-1">New Alias</label>
<div class="flex items-center gap-2">
<input type="text" name="local_part" required autocomplete="off" placeholder="alias" class="input-field flex-1">
<span class="text-sm text-zinc-500">@</span>
<div class="dropdown flex-1" data-dropdown>
<input type="hidden" name="domain_id" data-dropdown-value>
<button type="button" class="input-field text-left flex items-center justify-between" data-dropdown-trigger>
<span class="truncate" data-dropdown-label>Select domain</span>
<svg class="w-4 h-4 text-zinc-500 shrink-0 ml-2 transition-transform duration-150" data-dropdown-chevron fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="1.5">
<path stroke-linecap="round" stroke-linejoin="round" d="m19.5 8.25-7.5 7.5-7.5-7.5" />
</svg>
</button>
<div class="dropdown-menu" data-dropdown-menu>
<div class="p-2 border-b border-white/[0.04]">
<input type="text" placeholder="Search domains..." class="dropdown-search" data-dropdown-search>
</div>
<div class="dropdown-options" data-dropdown-options>
{% for domain in domains %}
<button type="button" class="dropdown-option" data-dropdown-option data-value="{{ domain.ID }}" data-label="{{ domain.Name }}.{{ domain.TLD.Name }}">
<p class="text-sm text-zinc-200">{{ domain.Name }}.{{ domain.TLD.Name }}</p>
</button>
{% endfor %}
</div>
<div class="dropdown-empty hidden" data-dropdown-empty>
<p class="text-xs text-zinc-500 text-center py-3">No domains found</p>
</div>
</div>
</div>
</div>
</div>
<button type="submit" class="btn-primary">Add Alias</button>
</form>
</div>
</div>
<div id="confirm-modal" class="fixed inset-0 z-50 hidden">
<div class="absolute inset-0 bg-black/60 backdrop-blur-sm" data-confirm-backdrop></div>
<div class="flex items-center justify-center min-h-screen p-4">
<div class="relative glass rounded-xl glow-border w-full max-w-sm p-6 space-y-4">
<div class="flex items-center gap-3">
<div class="flex items-center justify-center w-10 h-10 rounded-xl bg-red-500/10">
<svg class="w-5 h-5 text-red-400" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="1.5">
<path stroke-linecap="round" stroke-linejoin="round" d="M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0L2.697 16.126ZM12 15.75h.007v.008H12v-.008Z" />
</svg>
</div>
<h3 id="confirm-title" class="text-sm font-medium text-zinc-100"></h3>
</div>
<p id="confirm-message" class="text-xs text-zinc-400 leading-relaxed"></p>
<div class="flex items-center justify-end gap-3 pt-2">
<button data-confirm-cancel class="px-4 py-2 text-xs text-zinc-400 hover:text-zinc-200 rounded-lg bg-surface-800 border border-white/[0.06] hover:border-white/[0.1] transition-all duration-150">Cancel</button>
<button id="confirm-action" class="px-4 py-2 text-xs text-white rounded-lg bg-red-500/80 hover:bg-red-500 border border-red-400/20 transition-all duration-150">Delete</button>
</div>
</div>
</div>
</div>
</div>
|