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:
@@ -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):
|
||||
|
||||
Reference in New Issue
Block a user