feat: Add SMTP settings and collapsible email configuration UI

- Add SMTP fields to TicketEmailSettings model (host, port, TLS/SSL, credentials, from email/name)
- Update serializers with SMTP fields and is_smtp_configured flag
- Add TicketEmailTestSmtpView for testing SMTP connections
- Update frontend API types and hooks for SMTP settings
- Add collapsible IMAP and SMTP configuration sections with "Configured" badges
- Fix TypeScript errors in mockData.ts (missing required fields, type mismatches)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
poduck
2025-11-29 18:28:29 -05:00
parent 0c7d76e264
commit cfc1b36ada
94 changed files with 13419 additions and 1121 deletions

View File

@@ -99,6 +99,80 @@ Global registry for managing plugins.
- `list_all()` - List all plugins with metadata
- `list_by_category()` - Group plugins by category
#### Template Variables (`schedule/template_parser.py`)
Template variables allow plugins to define configurable fields that users can fill in via the UI.
**Variable Format:**
```
{{PROMPT:variable_name|description}}
{{PROMPT:variable_name|description|default_value}}
{{PROMPT:variable_name|description|default_value|type}}
{{PROMPT:variable_name|description||type}} (no default, explicit type)
```
**Supported Types:**
| Type | Description | UI Component |
|------|-------------|--------------|
| `text` | Single-line text input | Text input |
| `textarea` | Multi-line text input | Textarea |
| `email` | Email address | Email input with validation |
| `number` | Numeric value | Number input |
| `url` | URL/webhook endpoint | URL input with validation |
| `email_template` | Email template selector | Dropdown of email templates |
**Type Inference:**
If no explicit type is provided, the parser infers type from the variable name:
- Names containing `email``email` type
- Names containing `count`, `days`, `hours`, `amount``number` type
- Names containing `url`, `webhook`, `endpoint``url` type
- Names containing `message`, `body`, `content``textarea` type
- Default → `text` type
**Example - Email Template Variable:**
```python
# In your plugin script, reference an email template:
template_id = {{PROMPT:confirmation_template|Email template for confirmations||email_template}}
# The UI will show a dropdown of all available email templates
# The user selects a template, and the template ID is stored in the config
```
**Using Email Templates in Plugins:**
```python
from schedule.models import EmailTemplate
class MyNotificationPlugin(BasePlugin):
def execute(self, context):
template_id = self.config.get('confirmation_template')
if template_id:
template = EmailTemplate.objects.get(id=template_id)
subject, html, text = template.render({
'BUSINESS_NAME': context['business'].name,
'CUSTOMER_NAME': customer.name,
# ... other variables
})
# Send the email using the rendered template
send_email(recipient, subject, html, text)
```
**Insertion Codes (for use within templates):**
These codes are replaced at runtime with actual values:
- `{{BUSINESS_NAME}}` - Business name
- `{{BUSINESS_EMAIL}}` - Business contact email
- `{{BUSINESS_PHONE}}` - Business phone number
- `{{CUSTOMER_NAME}}` - Customer's name
- `{{CUSTOMER_EMAIL}}` - Customer's email
- `{{APPOINTMENT_TIME}}` - Appointment date/time
- `{{APPOINTMENT_DATE}}` - Appointment date only
- `{{APPOINTMENT_SERVICE}}` - Service name
- `{{TODAY}}` - Today's date
- `{{NOW}}` - Current date and time
### 3. Celery Tasks (`schedule/tasks.py`)
#### execute_scheduled_task(scheduled_task_id)
@@ -298,6 +372,11 @@ class MyCustomPlugin(BasePlugin):
'default': 100,
'description': 'Processing threshold',
},
'notification_template': {
'type': 'email_template',
'required': False,
'description': 'Email template to use for notifications',
},
}
def execute(self, context):