Jul 9 - Chat - save chat sessions
This commit is contained in:
@@ -319,6 +319,17 @@ support_ticket_replies: id, ticket_id (FK→support_tickets CASCADE), user_id (F
|
||||
body TEXT, created_at DATETIME
|
||||
```
|
||||
|
||||
### SupportChatSession / SupportChatMessage (Phase 37)
|
||||
|
||||
```
|
||||
support_chat_sessions: id, customer_id (FK→users CASCADE, indexed),
|
||||
created_at, updated_at (indexed)
|
||||
support_chat_messages: id, session_id (FK→support_chat_sessions CASCADE, indexed),
|
||||
role ('user'|'assistant'), content TEXT, created_at
|
||||
```
|
||||
|
||||
Persists the customer AI support chat. `chat_message()` writes both the user turn and the assistant reply into the session (creating one lazily on the first message; `session.updated_at` bumped each turn). `chat()` reloads the customer's **most recent** session into the chat window for continuity (unless `?new=1`). Read-only history views exist for the customer (`/support/my-conversations`) and staff (`/support/admin/conversations`). `SupportChatSession.preview` = first user message; `.message_count` for list views. See §18 "Support Chat".
|
||||
|
||||
**Flow:**
|
||||
- Customer submits ticket via chat page modal → status `open` → admins notified (in-app + email)
|
||||
- Admin replies → status auto-advances to `answered` → customer notified (in-app + email, link to `/support/my-tickets/<id>`)
|
||||
@@ -454,7 +465,7 @@ Management (`/scheduled-inspections/new|edit|delete`) is `@project_manager_requi
|
||||
| `reports` | `/reports` | index, facility report, scorecard, CSV/PDF/Excel export, issues-aging, sla-compliance, followup-closure, facility summary PDF |
|
||||
| `scheduled_reports` | `/scheduled-reports` | CRUD + manual trigger (accessible via Reports sub-nav) |
|
||||
| `scheduled_inspections` | `/scheduled-inspections` | list, new/edit/delete (PM+), `GET /<id>/start` (assigned inspector or manager → creates linked inspection), `POST /run` (cron reminders, `token=DIGEST_SECRET`) |
|
||||
| `support` | `/support` | `GET /chat`, `POST /chat/message` (AJAX→Groq), `POST /tickets`, `GET /my-tickets`, `GET/POST /my-tickets/<id>`, `GET /admin/tickets`, `GET/POST /admin/tickets/<id>` |
|
||||
| `support` | `/support` | `GET /chat` (loads latest saved session; `?new=1` to start fresh), `POST /chat/message` (AJAX→Groq; **persists** user+assistant turns, returns `session_id`), `GET /my-conversations`, `GET /my-conversations/<id>` (customer chat history), `GET /admin/conversations`, `GET /admin/conversations/<id>` (staff, read-only), `POST /tickets`, `GET /my-tickets`, `GET/POST /my-tickets/<id>`, `GET /admin/tickets`, `GET/POST /admin/tickets/<id>` |
|
||||
| `broadcast` | `/admin/broadcast` | `GET /` (compose + history), `POST /send` (admin-only; fans out one Notification per targeted user) |
|
||||
| `devices` | `/admin/devices` | `GET /` (device list from `api_device_tokens`), `POST /notify` (admin-only) |
|
||||
| `api` | `/api/v1` | parent blueprint |
|
||||
@@ -761,7 +772,8 @@ phase1_projects_roles → phase6_features → phase7_mobile_api → phase8_notif
|
||||
→ phase33_contract_recipients
|
||||
→ phase34_facility_qr
|
||||
→ phase35_issue_handler
|
||||
→ phase36_scheduled_insp ← HEAD
|
||||
→ phase36_scheduled_insp
|
||||
→ phase37_support_chat ← HEAD
|
||||
```
|
||||
|
||||
### phase21_performance_indexes
|
||||
@@ -880,6 +892,16 @@ sudo systemctl restart gunicorn
|
||||
# -d "token=YOUR_DIGEST_SECRET"
|
||||
```
|
||||
|
||||
### phase37_support_chat
|
||||
|
||||
Revision id `phase37_support_chat`. Creates `support_chat_sessions` + `support_chat_messages` so the customer AI support-chat is persisted (see §5 and §18 "Support Chat"). Table existence checks — safe to re-run.
|
||||
|
||||
**Deploy order:**
|
||||
```bash
|
||||
flask db upgrade
|
||||
sudo systemctl restart gunicorn
|
||||
```
|
||||
|
||||
**Deploy order for phases 24–32:**
|
||||
```bash
|
||||
flask db upgrade
|
||||
@@ -1097,9 +1119,10 @@ A **PDF Summary** button was added to `reports/scorecard.html` alongside the exi
|
||||
|
||||
`GET /support/chat` — customer only. Renders:
|
||||
- Greeting message with `current_user.display_name` (injected via `var userName = {{ current_user.display_name | tojson }}` — use `tojson` not inline interpolation to prevent XSS/quote breaks).
|
||||
- FAQ quick-reply chips: text stored in `data-faq="..."` HTML attribute (HTML-escaped with `| e`), read in JS via `btn.dataset.faq`. **Never use `| tojson` in an `onclick=""` attribute** — it emits double-quoted JSON inside a double-quoted attribute, breaking HTML parsing and truncating the `<script>` tag.
|
||||
- FAQ quick-reply chips: text stored in `data-faq="..."` HTML attribute (HTML-escaped with `| e`), read in JS via `btn.dataset.faq`. **Never use `| tojson` in an `onclick=""` attribute** — it emits double-quoted JSON inside a double-quoted attribute, breaking HTML parsing and truncating the `<script>` tag. **The FAQ section stays visible for the whole session** (phase37) — it is NOT hidden after the first message, and chips are not disabled after clicking (reusable throughout).
|
||||
- Chat history kept client-side in `let history = []`, sent with each AJAX `POST /support/chat/message`. Server caps at last 20 turns.
|
||||
- If `GROQ_API_KEY` is absent, input is disabled and a fallback "Submit to Support" link is shown.
|
||||
- **Persistence (phase37):** conversations are saved to `support_chat_sessions` / `support_chat_messages`. The page reloads the customer's most recent session into the window (continuity) unless `?new=1`. `let sessionId` (seeded from `chat_session_id`) is sent with each message and updated from the response; the server persists both turns. Header buttons: **History** (`/support/my-conversations`) and **New** (`/support/chat?new=1`). Staff can review any customer's chats read-only at `/support/admin/conversations`. Both detail views `{% include 'support/_transcript.html' %}`.
|
||||
- If `GROQ_API_KEY` is absent, input is disabled and a fallback "Submit to Support" link is shown (the reply is still persisted).
|
||||
- "Submit to Support" modal POSTs to `POST /support/tickets`; subject pre-filled from last user message in history.
|
||||
|
||||
### Inspection Execute Page — UX Patterns
|
||||
|
||||
Reference in New Issue
Block a user