.
This commit is contained in:
parent
c75b5889cf
commit
1e3f8dc1ad
40
CLAUDE.md
Normal file
40
CLAUDE.md
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
# CLAUDE.md
|
||||||
|
|
||||||
|
Context for Claude Code sessions in this repo. Keep this short. Longer notes live in `docs/`.
|
||||||
|
|
||||||
|
## Project
|
||||||
|
|
||||||
|
A help desk dashboard for ManageEngine ServiceDesk Plus Cloud (`ithelp.mainecc.edu`). It currently runs as a single Node/Express server. The central region (KVCC, EMCC, CMCC, MCCS) is configured through `.env`.
|
||||||
|
|
||||||
|
- **Goal:** multi-region, multi-user, customisable. See `docs/ROADMAP.md`.
|
||||||
|
- **Decisions, API gotchas and known issues:** `docs/NOTES.md`. Read it before touching any SDP query.
|
||||||
|
- **Latest session summary and handoff:** `SESSION.md`.
|
||||||
|
|
||||||
|
## Run
|
||||||
|
|
||||||
|
```text
|
||||||
|
npm install
|
||||||
|
npm run app # node src/server.js from the repo root; .env lives in the repo root
|
||||||
|
```
|
||||||
|
|
||||||
|
The app is served at <http://localhost:3000>. Sign in with the Connect button, which uses Zoho's device-code flow.
|
||||||
|
|
||||||
|
## Layout
|
||||||
|
|
||||||
|
- `src/server.js`: reads `.env` and starts everything.
|
||||||
|
- `src/auth.js`: Zoho device-code sign-in.
|
||||||
|
- `src/boardService.js`: token, state and refresh timers.
|
||||||
|
- `src/tickets.js`: all SDP queries (closed feed, status table, closed today, unassigned).
|
||||||
|
- `src/weather.js`: OpenWeatherMap, cached for 10 minutes.
|
||||||
|
- `src/routes.js`: the `/api/*` routes.
|
||||||
|
- `src/public/index.html`: the whole front end in one file (inline CSS and JS, no build step).
|
||||||
|
|
||||||
|
## Working agreements
|
||||||
|
|
||||||
|
- Never print or commit `.env` values (Zoho client secret, OpenWeatherMap key). Redact them when inspecting.
|
||||||
|
- There are no automated tests yet. Verify server logic by stubbing `axios.get`. Resolve axios from the project with `require.resolve('axios', { paths: [dir] })` so the stub hits the same instance. Verify the page by evaluating its `<script>` with stubbed `document` and `fetch`, or by taking a screenshot with headless Edge.
|
||||||
|
- The sandbox can't start a second server instance; it can't bind ports. Screenshots of the live app use the user's running server on port 3000.
|
||||||
|
- Match the existing style: 4-space indent and CommonJS on the server, 2-space indent in `index.html`, lowercase `//` comments explaining why rather than what. Some files have CRLF line endings, so use the Edit tool rather than sed for multi-line changes.
|
||||||
|
- Keep the core closed-ticket watcher (feed and ding) working and on by default.
|
||||||
|
- Don't commit unless asked. Commit messages end with the Co-Authored-By line for Claude.
|
||||||
|
- Record new decisions and gotchas in `docs/NOTES.md`, and move roadmap items as they're done.
|
||||||
53
SESSION.md
Normal file
53
SESSION.md
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
# Session summary: 2026-10-15
|
||||||
|
|
||||||
|
A Claude Code session that turned the closed-ticket board into a dashboard. Background is in `CLAUDE.md`, `docs/ROADMAP.md` and `docs/NOTES.md`.
|
||||||
|
|
||||||
|
## Where things stand
|
||||||
|
|
||||||
|
The dashboard is running and working against live SDP data for the central region. All the work below is in the working tree. The last few files (`CLAUDE.md`, `docs/`, `SESSION.md`) may still be uncommitted.
|
||||||
|
|
||||||
|
## What was built, in order
|
||||||
|
|
||||||
|
1. **Dashboard redesign** (`index.html`, `tickets.js`, `boardService.js`): stat tiles; a technician × status table with Total open and Closed today columns; the live closed feed in a side column; a "Sound on close" toggle, on by default; Refresh now. The table refreshes every `WORKLOAD_MINUTES` (default 5). The closed watcher still checks every minute.
|
||||||
|
2. **Central region scoping:** `SITE_NAMES` and `GROUP_NAMES` in `.env` are applied to every SDP query, and each ticket is also re-checked locally.
|
||||||
|
3. **Unassigned requests counter:** `UNASSIGNED_EXCLUDED_STATUSES` mirrors the ManageEngine "Central Region Unassigned" view. **Verified to match the view exactly.** The debug list is kept but hidden (`SHOW_UNASSIGNED_LIST = false` in `index.html`).
|
||||||
|
4. **Weather card** (`src/weather.js`, `/api/weather`): OpenWeatherMap current weather and 5-day forecast with icons, using `OWM_API_KEY` and `OWM_ZIP_CODE`, cached for 10 minutes. Working.
|
||||||
|
5. **Sign-in changes:** the Zoho page opens in a new tab, the button only appears once the device code exists, and the page checks quickly after Connect is clicked.
|
||||||
|
6. **Table layout:** totals moved to the left so they don't get cut off; the auth panel text is wider.
|
||||||
|
7. **SDP query fixes:**
|
||||||
|
- `greater_than` → `greater than`. The wrong spelling made SDP ignore all the criteria and return about 124k tickets.
|
||||||
|
- Paging now dedupes by ID and stops early when the total can't be reached.
|
||||||
|
- The "partial" note now names which query was cut off.
|
||||||
|
- **Verified fixed:** the "partial" note is gone.
|
||||||
|
8. **Small fixes:** `[hidden]` CSS bug (Refresh now showed when disconnected); a misplaced comment in `server.js`.
|
||||||
|
9. **README rewritten**, with new screenshots in `images/`. `1.png` and `2.png` are rendered with sample data; `4.png` is from the live server; `3.png` is unchanged.
|
||||||
|
10. **Credits:** page footer, README, `package.json` contributors, `server.js` header. Isaac Godin keeps the design credit.
|
||||||
|
11. **License:** MIT (LICENSE copyright Skylar Grant; package.json now says MIT, not ISC).
|
||||||
|
12. **Repo structure for working with Claude:** `CLAUDE.md`, `docs/ROADMAP.md`, `docs/NOTES.md`.
|
||||||
|
|
||||||
|
## Settings added to `.env` this session
|
||||||
|
|
||||||
|
`SITE_NAMES`, `GROUP_NAMES`, `UNASSIGNED_EXCLUDED_STATUSES`, `WORKLOAD_MINUTES` (optional), `OWM_API_KEY`, `OWM_ZIP_CODE`. All are documented in `src/env.example` and the README.
|
||||||
|
|
||||||
|
## Known issues
|
||||||
|
|
||||||
|
- **The Zoho token expires after about an hour and is lost on restart.** `auth.js` throws away the `refresh_token`. This is the first thing to fix before hosting.
|
||||||
|
- On a typical screen the status table scrolls sideways ("Need Info" gets cut off), because the page is capped at 1,320px.
|
||||||
|
- Anyone who can reach the URL can see the data and click Connect or Refresh. That's fine locally, not when hosted.
|
||||||
|
|
||||||
|
## Next steps
|
||||||
|
|
||||||
|
Planned direction: hosted, multi-region, per-user. See `docs/ROADMAP.md`.
|
||||||
|
|
||||||
|
1. **Phase 1:** store and auto-renew the refresh token, save it so it survives restarts, and make Connect and Refresh admin-only.
|
||||||
|
2. **Phase 2:** regions as configuration in SQLite, with the current `.env` settings as the first region, "Central", plus a region switcher.
|
||||||
|
3. Then user sign-in, admin pages and Docker.
|
||||||
|
|
||||||
|
**Answer these before phase 3:**
|
||||||
|
- Are regions a security boundary or a convenience?
|
||||||
|
- Microsoft or Zoho sign-in for staff?
|
||||||
|
- Does SDP restrict technicians to certain sites?
|
||||||
|
|
||||||
|
## To pick up
|
||||||
|
|
||||||
|
Start a Claude Code session in this repo and say something like: *"Read SESSION.md and docs/ROADMAP.md, then start phase 1."*
|
||||||
27
docs/NOTES.md
Normal file
27
docs/NOTES.md
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
# Notes
|
||||||
|
|
||||||
|
## SDP v3 API gotchas
|
||||||
|
|
||||||
|
Docs: <https://www.manageengine.com/products/service-desk/sdpod-v3-api/getting-started/search-criteria.html>
|
||||||
|
|
||||||
|
- **Condition names have spaces:** `greater than`, `is not`, `lesser than`. `greater_than` isn't valid, and SDP silently ignored the **entire** search criteria because of it, returning every ticket (124,050). If a query's `total_count` is huge, suspect the criteria first.
|
||||||
|
- **Paging:** `row_count` is at most 100. Use `start_index`, and stop when `list_info.has_more_rows` is false. Ask for `get_total_count: true` on the first page. `getAllRequests` dedupes by ID and stops at 20 pages or when the total is unreachable.
|
||||||
|
- **Multiple values:** use a `values: [...]` array, and join criteria with `logical_operator: 'AND'` (see `allOf()` in `tickets.js`).
|
||||||
|
- **"Technician is empty":** written as `{ field: 'technician', condition: 'is' }` with no value. This isn't documented, since the docs only show the "is not" form, but it's verified to work.
|
||||||
|
- **Field names that work in filters:** `site.name`, `group.name`, `technician.name`, `status.name`, `last_updated_time`.
|
||||||
|
- **Group names:** the ManageEngine UI shows groups as "Customer Support « KVCC", but the API name is plain "Customer Support".
|
||||||
|
- **Sign-in scope:** `SDPOnDemand.requests.READ` is enough for everything so far.
|
||||||
|
- **Token lifetime:** Zoho access tokens last about an hour. Refresh tokens aren't stored yet (roadmap phase 1).
|
||||||
|
|
||||||
|
## Decisions
|
||||||
|
|
||||||
|
- **2026-10-15:** **MIT license.** Copyright Skylar Grant.
|
||||||
|
- **2026-10-15:** **OpenWeatherMap** for weather. The free tier covers current weather and the 5-day forecast, and results are cached for 10 minutes. The National Weather Service API was the alternative (free, no key), but it needs three calls per lookup.
|
||||||
|
- **2026-10-15:** **Unassigned counter** uses its own status exclusions (`UNASSIGNED_EXCLUDED_STATUSES`) to match the ManageEngine view. The debug list is kept but hidden (`SHOW_UNASSIGNED_LIST` in `index.html`).
|
||||||
|
- **2026-10-15:** **Multi-region approach:** one service token plus region config, not per-user Zoho tokens. A user's own token could see all 124k tickets, so it wouldn't separate regions, and per-user polling multiplies API traffic. See `ROADMAP.md`.
|
||||||
|
|
||||||
|
## Known issues
|
||||||
|
|
||||||
|
- The status table scrolls sideways once there are more statuses than fit, because the page is capped at 1,320px. Consider widening the page or narrowing the sidebar.
|
||||||
|
- All statuses not in `STATUS_NAMES` count as open, including "Need Information" and "On Hold". This is intentional for now; revisit when regions get their own config.
|
||||||
|
- The token is lost on restart and expires after about an hour.
|
||||||
37
docs/ROADMAP.md
Normal file
37
docs/ROADMAP.md
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
# Roadmap
|
||||||
|
|
||||||
|
## Goal
|
||||||
|
|
||||||
|
A hosted dashboard where staff in each MCCS region sign in and see their own region's queue. It should be customisable per user, and easy to extend with new panels.
|
||||||
|
|
||||||
|
## Target architecture
|
||||||
|
|
||||||
|
- **Identity:** users sign in (Zoho web OAuth, or Microsoft if MCCS staff use it) only to identify themselves.
|
||||||
|
- **Data:** one service connection, signed in once by an admin, with its refresh token kept and auto-renewed. Its SDP account must be able to see every region.
|
||||||
|
- **Regions:** profiles stored in SQLite (sites, groups, technicians, statuses). Checks run once per region and the results are cached, so API traffic grows with regions, not viewers.
|
||||||
|
- **Access:** users are assigned to regions and the server enforces it. An admin role manages regions and assignments.
|
||||||
|
- **Extensibility:** each panel is a module with server code to fetch its data and page code to draw it. The weather card is the first example.
|
||||||
|
|
||||||
|
## Phases
|
||||||
|
|
||||||
|
- [ ] **1. Keep the token alive:** store the Zoho `refresh_token` (currently thrown away in `auth.js`), auto-renew the hourly access token, and save it to a file or the database so it survives restarts.
|
||||||
|
- [ ] **1b. Admin-only actions:** make `/api/connect` and `/api/check` admin-only.
|
||||||
|
- [ ] **2. Regions as configuration:** one board service per region, `/api/regions/:id/...` routes, and a region switcher on the page. The current `.env` settings become the first region, "Central".
|
||||||
|
- [ ] **3. User sign-in:** web OAuth, sessions, user-to-region mapping, admin role. Needs a "Server-based Application" client in the Zoho console and HTTPS on a real hostname.
|
||||||
|
- [ ] **4. Admin pages:** edit regions and assign users.
|
||||||
|
- [ ] **5. Deployment:** Dockerfile and docker-compose with `env_file: .env` and a volume for the database and token.
|
||||||
|
- [ ] **Later:** per-user preferences (default region, hidden columns, sound) and panel modules.
|
||||||
|
|
||||||
|
## Open questions
|
||||||
|
|
||||||
|
- Are regions a **security boundary** (staff can't see other regions) or a **convenience** (default view with a switcher)?
|
||||||
|
- Do MCCS staff sign in with Microsoft 365 or Entra ID? That decides between Zoho and Microsoft sign-in.
|
||||||
|
- Does SDP itself restrict technicians to certain sites? If it does, per-user tokens become an option.
|
||||||
|
|
||||||
|
## Done
|
||||||
|
|
||||||
|
- Dashboard: stat tiles, technician × status table, live closed feed with the ding.
|
||||||
|
- Central region scoping by site and group.
|
||||||
|
- Unassigned counter. Verified to match the ManageEngine "Central Region Unassigned" view on 2026-10-15.
|
||||||
|
- Weather card (OpenWeatherMap).
|
||||||
|
- Fixed SDP paging and the date filter (see `NOTES.md`).
|
||||||
Loading…
Reference in New Issue
Block a user