# ActionLog UI — Handoff, Architecture & Functional Specification

**Project:** `actionsui`  
**Stack:** jQuery, vanilla JS, HTML/CSS (no build step, no framework)  
**API backend:** `../actionsapi`  
**Last updated:** 2026-05-29  

---

## 1. Purpose

Single-page web application for **ActionLog**: browse, search, create, and manage **past actions** and their related **clients, leads, projects, targets**, with a **timeline/conversation view** and **settings** for master data and helper options.

This is a **log viewer**, not a task manager. All dates refer to when something **already happened**.

---

## 2. Architecture Overview

```
Actions.html
    ├── Actions.css          All styles, view transitions, layout
    ├── js/Common.js         Shared: apipost, forms, rich editor, WhatsApp parser
    └── Actions.js           Module logic: Actions() constructor + Setup()
```

### Request flow

```
User action → Actions.js handler
                  ↓
              apipost('module.php', {command, apikey, ...})
                  ↓
              actionsapi (JSON response)
                  ↓
              Render DOM / switch view
```

### View system

CSS classes on `.ActionsModule` control which panel is visible:

| Class | Panel |
|-------|-------|
| `ShowList` | Main actions list |
| `ShowAction` | Single action detail |
| `ShowForm` | New/edit form (action, entity, or helper) |
| `ShowTimeline` | Timeline with entity sidebar + conversation |
| `ShowSettings` | Settings grid (CRUD lists) |

Panels use absolute positioning inside `.ViewStack` with opacity/transform transitions. Layout is **viewport-height constrained** — scroll happens inside list areas, not the page body.

---

## 3. File Structure

```
actionsui/
├── Actions.html           Main page, all view panels
├── Actions.css            Styles
├── Actions.js             Application logic
├── js/
│   └── Common.js          Reusable utilities
├── .cursorrules           Frontend coding conventions
└── innerdocs/
    ├── HANDOFF.md         This document
    ├── ZAMMAD_SETUP.md    Step-by-step Zammad → Actions integration guide
    └── app_sample/        Reference samples (Contacts, Customers patterns)
```

---

## 4. Authentication

Top bar **ApiKeyInput** (default `sample-key-123`). Every `apipost()` call adds:

```javascript
obj.apikey = $('.ApiKeyInput').val();
```

Token-based login is supported by the API but the UI currently uses **API key only**. To add login UI later: store token, send `obj.token` instead of/in addition to apikey.

API root is derived from URL:

```javascript
// Common.js — maps /actionsui/ → /actionsapi/
apiroot() + 'actions.php'
```

---

## 5. Views & Features

### 5.1 Top bar

| Control | Action |
|---------|--------|
| ApiKeyInput | Sets apikey for all requests |
| Actions | `actions.list()` — main list view |
| Timeline | `actions.timeline()` — timeline view |
| New action | `actions.new()` — action form |
| ⚙ Settings | `actions.settings()` — settings view |

### 5.2 Actions list (`ShowList`)

- **No column filters** — global search only
- Search scans all fields client-side (`JSON.stringify(record)`)
- Toolbar: search input + Search + Clear
- List loads `actions.php` `command=list`, limit 500
- **Row max-height 120px** — long descriptions truncated (title ellipsis, description 3-line clamp)

Columns: title/preview, type pill, client/lead/target, project, date.

Click row → action detail view.

### 5.3 Action detail (`ShowAction`)

- Compact view: title, meta pills (type, area, date), **HTML action body**, relation boxes
- Edit → form view
- Delete → confirm + `actions.php` delete

### 5.4 Action form (`ShowForm` + ActionForm)

Fields: action (rich text), title, type, area, client/lead/project/target (id or nickname), when, duration, tags (datalist), source.

**Type and area** selects populated from `helpers.php` `getall`.

**Tags** use `<datalist>` — select existing or type new (backend creates on save).

**Rich text editor** on action field:
- Toolbar: Bold, Italic, Underline, bullets, numbered list, link, quote, horizontal rule, clear format
- Content stored as HTML in `action` field

**WhatsApp paste formatting** (when type = `whatsapp`):
- Detects export format: `[HH:MM, DD/M/YYYY] Sender: message`
- Converts to bubble HTML (60% width, first sender left, second sender right)
- Works on paste and when switching type to whatsapp

### 5.5 Timeline (`ShowTimeline`)

Two-column layout inside viewport height.

#### Left sidebar — entity picker

| Control | Behavior |
|---------|----------|
| Filter pills | All, C (clients), P (projects), L (leads), T (targets) — single line, icons |
| Search | Searches all entity tables when All; one table when filtered |
| Entity list | Scrollable; sorted by latest action date (All) or entity modified (filtered) |

Selecting entity → loads `actions.php` `gettimeline` with that entity id → chronological action list on right.

#### Right panel — conversation

| Area | Behavior |
|------|----------|
| Header | Entity name, event count, Add action button |
| Type filters | All, Email, WhatsApp, Calls, Meetings, Notes, AI activity |
| ConversationList | Scrollable; actions oldest→newest; **HTML rendered** |
| Quick add box | Fixed at bottom |

**Quick add box:**

1. **Type tabs** — dynamic from `action_types` helper table
2. **Rich text editor** — same toolbar (compact); WhatsApp paste support when WhatsApp tab selected
3. **Meta row:** tag (~25% width) | when (datetime-local, prefilled now) | area pills (dynamic from helpers)
4. Send → `actions.php` add with prefilled `clientid`/`leadid`/`projectid`/`targetid` from selected entity

### 5.6 Settings (`ShowSettings`)

Scrollable 2-column grid. Each section: title, + button, list with Edit/Delete.

| Section | API |
|---------|-----|
| Projects | Projects.php |
| Types | ActionHelpers.php helpertable=type |
| Areas | ActionHelpers.php helpertable=area |
| Tags | ActionHelpers.php helpertable=tag |

Clients, leads, and targets are **not** edited here — they come from CRM **Contacts.php** (`typename` = client / lead / vendor). Timeline filters and action relations still load them via that API at runtime.

**Logger / integration panels** (full-width sections below the grid):

| Section | API command | Purpose |
|---------|-------------|---------|
| Email Logger | `syncemaillogger` | 60-day backfill from EmailLog |
| WhatsApp Logger | `syncwhatsapplogger` | 60-day backfill from WhatsAppLog |
| Zammad tickets | `getzammadsettings`, `savezammadsettings`, `synczammad` | Zammad domain, webhook URL, 30-day backfill |

Setup guide: [`ZAMMAD_SETUP.md`](ZAMMAD_SETUP.md)

Add/Edit opens form view:
- **EntityForm** — name, nickname, company, email, phone, description
- **HelperForm** — value, label

`formreturnview = 'settings'` ensures Back/Save returns to settings.

---

## 6. JavaScript Architecture

### 6.1 Module pattern (`Actions.js`)

```javascript
actions = new Actions;
actions.setup();

function Actions() {
    this.list = list;
    this.timeline = timeline;
    // ... public methods bound in constructor

    var selectedaction = null;
    var timelineentity = null;
    var helperrecords = {type:[], area:[], tag:[]};
    var formreturnview = 'list';

    function Setup() {
        setupricheditors();
        loadselectors(...);
        loadhelpers(...);
        list();
    }
}
```

Internal callbacks exposed via `window.actionsinternal` for inline `onclick` handlers (list item click, settings edit, timeline entity select, quick type/area index).

### 6.2 Common.js utilities

| Function | Purpose |
|----------|---------|
| `apipost(file, obj, callback)` | POST JSON to API |
| `formobject(selector)` | Serialize form to object |
| `setform(selector, record)` | Populate form (+ rich editor for action) |
| `clearmoduleclasses()` | Reset view classes |
| `escapehtml()` | Safe text in attributes/list previews |
| `striphtmltags()` | Plain text from HTML |
| `actiondisplayhtml(html, type)` | Render action HTML; auto-format WhatsApp paste on display |
| `setupricheditors()` | Bind rich editor events |
| `richeditorcmd()` | execCommand toolbar actions |
| `parsewhatsapppaste()` / `whatsapppastetohtml()` | WhatsApp export → bubble HTML |
| `formatdate()` / `shortago()` | Date display |

### 6.3 State variables (key)

| Variable | Purpose |
|----------|---------|
| `selectedaction` | Current action in detail/edit |
| `timelineentity` | `{field, id, name, typename}` for timeline filter |
| `activetimelinefilter` | Conversation type filter |
| `activetimelineentityfilter` | Sidebar entity type filter |
| `activequicktype` / `activequickarea` | Timeline quick-add selections |
| `helperrecords` | Cached types, areas, tags |
| `entityrecords` | Cached clients, leads, projects, targets |
| `formreturnview` | `'list'` or `'settings'` for back navigation |

---

## 7. CSS Layout Model

| Element | Behavior |
|---------|----------|
| `html, body` | `height: 100%`, `overflow: hidden` |
| `.ActionsApp` | `height: 100dvh`, flex column |
| `.ViewStack` | `flex: 1`, `min-height: 0` |
| `.ViewPanel` | Absolute fill, flex column, `overflow: hidden` |
| `.List`, `.TimelineEntityList`, `.ConversationList` | `overflow-y: auto` inside fixed viewport |
| `.QuickActionBox` | `flex-shrink: 0` — stays visible at bottom |

View transitions: opacity + translateX on `.ViewPanel`.

---

## 8. API Integration Map

| UI feature | Endpoint | command |
|------------|----------|---------|
| Actions list | actions.php | list |
| Action CRUD | actions.php | add, update, delete, getrecord |
| Timeline actions | actions.php | gettimeline |
| Entity lists | {clients,leads,projects,targets}.php | list |
| Entity search | *.php | search |
| Entity CRUD | *.php | add, update, delete |
| Helper options | helpers.php | getall, list, add, update, delete |
| Settings helper CRUD | helpers.php | + helpertable=type\|area\|tag |

---

## 9. HTML Content in Actions

The `action` field **stores and displays HTML**:

| Location | Rendering |
|----------|-----------|
| List preview | Plain text (striphtmltags) |
| Detail view | Full HTML (`.RichHtmlContent`) |
| Timeline bubbles | Full HTML + WhatsApp bubble layout |
| Forms | Rich editor → HTML hidden input |

WhatsApp-specific: pasted export text becomes structured bubble HTML before save; stored HTML includes `.WhatsAppChat` wrapper.

---

## 10. Coding Conventions

See `.cursorrules`. Summary:

- Lowercase function names, no underscores
- Constructor `Actions()` with `this.method = method` bindings
- jQuery `$.post` via `apipost`
- Callback pattern: `if (callbackfunction != undefined) { callbackfunction(); }`
- If/else always with braces — no early `return` to skip else
- Reusable code in `Common.js`; module-specific in `Actions.js`

---

## 11. Database Reference

The UI does not connect to the database directly. Full schema and table definitions:

**→ [`../actionsapi/innerdocs/HANDOFF.md`](../actionsapi/innerdocs/HANDOFF.md)**  
**→ [`../actionsapi/schema.sql`](../actionsapi/schema.sql)**

Key tables the UI touches via API:

| Table | UI usage |
|-------|----------|
| actions | List, detail, timeline, forms |
| clients, leads, projects, targets | Settings, timeline sidebar, action relations |
| action_types | Type select, timeline quick tabs |
| action_areas | Area select, timeline quick area pills |
| action_tags | Tag datalist, settings |
| apikeys | Auth input |

---

## 12. Local Development

1. Ensure MariaDB running with `actionsdb` from `schema.sql`
2. Serve via Apache (or equivalent) under `/WebSite/actionsui/Actions.html`
3. API at `/WebSite/actionsapi/`
4. Default apikey: `sample-key-123`

Test API independently: `actionsapi/curl-examples.md`

---

## 13. Future Enhancements (not implemented)

- Login UI with session token instead of raw apikey
- Dynamic timeline type filters from helper table (currently hardcoded pills)
- Pagination on actions list (currently limit 500)
- AI draft button in timeline quick-add (placeholder UI only)
- Mobile-specific timeline layout refinements

---

## 14. Related Documentation

| File | Content |
|------|---------|
| `../actionsapi/innerdocs/HANDOFF.md` | API + database handoff |
| `../actionsapi/innerdocs/actionlog-api-spec.md` | Detailed API spec |
| `../actionsapi/curl-examples.md` | API test commands |
| `innerdocs/app_sample/` | Reference UI patterns from other projects |
