Details tab card layout ----------------------- The Details tab sat on .content-grid, a two-column CSS grid. Grid packs items into implicit rows, so every row is as tall as its tallest card and align-items:start leaves the shorter one with dead space beneath it: Warranty is short, Endpoint Status is tall, and Policy had to wait for the taller of the two rather than sliding up. That read as a staggered layout. Switched that one tab to multicol via a .details-flow modifier, which has no rows at all - each card starts where the previous one ended, so the holes close while cards still size to their content. Multicol is deliberately NOT applied to .content-grid globally. The note by that rule in style.css records why it was abandoned there: a column-span:all child (.pap-span, used by table panels) overlaps the shorter column when the two are unequal. That cannot happen on this tab - every panel in the details group is a keyvalue or list render, and spansFullWidth() only returns true for table (or a tabs panel holding one), so nothing in the subtree spans. Monitors and Service/Process DO carry table panels and stay on grid. The modifier is scoped to PCDetail, so the nine other detail views on .content-grid are untouched. Chosen over JS masonry on purpose. Masonry packs perfectly but has to measure every card and re-measure on resize, on panel collapse and on every async panel load - and these panels fetch after paint, so it would mean continuous forced reflow on a page that already polls. This is pure CSS: no measurement, no observer, no runtime cost. The tradeoff accepted is that column bottoms can end at slightly different heights. Cards carry break-inside: avoid so none fragments across the column break, and the 25px spacing returns as a margin because multicol has no gap between stacked items the way grid does. IP Configuration card --------------------- Removed: the data has no purpose on the page anymore. Taken out at the root rather than hidden - the panel declaration, the /asset/<id>/ipconfig route and the _IPCONFIG_COLUMNS constant all go, since a route with no consumer is dead surface that still answers requests. test_the_two_cards_do_not_duplicate_columns_beyond_the_address existed only to police the history/config column split; with one card gone it guards nothing, so it and its import go with it. The panel-count assertion in test_endpoints_asset_panels_are_computer_scoped moves 15 -> 14, which is the test doing its job and catching the removal. IP History is unchanged and still carries the address list. Not addressed here: three tzset() tests in test_endpoints_plugin.py fail on Windows because time.tzset() is Unix-only. Verified pre-existing against unmodified code; they pass in the Linux container.
100 lines
5.1 KiB
Markdown
100 lines
5.1 KiB
Markdown
# Copilot instructions for shopdb-flask
|
|
|
|
Follow these when suggesting code. They are enforced by a naming/style hook and
|
|
by CI (`.github/workflows/ci.yml`) - suggestions that break them fail the build.
|
|
`CONTRIBUTING.md` is the full authority; this is the short version.
|
|
|
|
## General Guidelines
|
|
- Finish the in-flight task before starting new workstreams.
|
|
- When asked to "take notes" on a future idea, capture it in the notes file only - do not implement it, and do not expand on it at length in replies.
|
|
- Use a temp file for multi-line git commit messages instead of heredoc syntax: `git commit -F <file>`.
|
|
- Avoid using `powershell.exe -File` for launching scripts, as it fails if the script file is missing or quarantined.
|
|
|
|
## Naming (LOCKED - the hook rejects violations)
|
|
|
|
- **DB tables**: lowercase, concatenated, plural. No underscores, no dashes.
|
|
`machines`, `networkdevices`, `businessunits` - NOT `machine_types`, `BusinessUnits`.
|
|
- **DB columns**: lowercase, concatenated, singular. No underscores.
|
|
`machineid`, `lastzabbixsync`, `isactive` - NOT `machine_id`, `last_zabbix_sync`.
|
|
- **Foreign keys**: referenced table (singular) + `id`: `locationid`, `vendorid`.
|
|
- **Booleans**: `is`/`has` prefix: `isactive`, `isshopfloor`.
|
|
- **Index names**: `idx_<table>_<column>` (underscores allowed here only).
|
|
|
|
### Python
|
|
|
|
- A variable, attribute, function, or dict key that holds a DB value MUST match
|
|
the column name exactly - do NOT convert to snake_case.
|
|
Column `machineid` -> `Machine.machineid`, `{"machineid": 1}`, local `machineid`.
|
|
- Pure code that does NOT mirror a DB field uses normal snake_case (PEP 8):
|
|
`loop_count`, `current_user`, `validate_input()`.
|
|
- Classes: PascalCase, spelled out (`NetworkDevice`, `AssetType`).
|
|
|
|
### JavaScript / Vue
|
|
|
|
- A JS variable holding an API field value matches the API key exactly - do NOT
|
|
camelCase it. API `{"machineid": 1}` -> `response.machineid`, never `machineId`.
|
|
- Components: PascalCase (`AssetDetail.vue`). CSS classes: lowercase-with-dashes.
|
|
|
|
### API
|
|
|
|
- Endpoints: lowercase plural nouns, no underscores/dashes: `/api/networkdevices`.
|
|
- Query params + response keys match column names: `?locationid=5`,
|
|
`{"machineid": 1, "lastzabbixsync": "..."}`.
|
|
|
|
### Allowed acronyms only
|
|
|
|
Universal: id url api http https json jwt sql os ip dns csv pdf cors ttl uuid
|
|
html css orm. Domain: cmm cnc pc usb vnc winrm ssh ssl tls tcp udp smtp ldap
|
|
vlan sso dnc focas clm mtconnect. Anything else: spell it out.
|
|
|
|
### Banned shorthand
|
|
|
|
Never use `cfg ctx mgr req res env util helper` or `db` as a standalone variable
|
|
name. Spell out: `config context manager request response environment utilities`.
|
|
`_bp` is fine only as a suffix with a meaningful prefix (`printers_bp`).
|
|
|
|
## Style (ASCII only)
|
|
|
|
- NO emojis anywhere - code, comments, strings, UI.
|
|
- NO em-dashes, en-dashes, Unicode arrows, or smart quotes. Plain ASCII only.
|
|
- Comments default to NONE. Add one only when the WHY is non-obvious; keep inline
|
|
`#`/`//` comments terse. Docstrings stay normal English.
|
|
- Dark theme is the default; keep UI functional and professional.
|
|
|
|
## Architecture (do not violate)
|
|
|
|
- **Plugins are the product.** Plugin code lives in `plugins/<name>/{models,api,services,schemas}/`
|
|
with a `manifest.json` (single source of truth: name, version, dependencies,
|
|
api_prefix) and a `BasePlugin` subclass in `plugin.py`.
|
|
- **Plugins never import core internals.** Use the contract surface `shopdb.api`
|
|
(e.g. `from shopdb.api import db, Asset, success_response`). Adding to that
|
|
surface is a contract-version bump + a `docs/PLUGIN-HOOKS` update in the same PR.
|
|
- **Migrations, never `db.create_all()`.** The core Alembic chain is in
|
|
`migrations/versions/`; each plugin owns its own chain under
|
|
`plugins/<name>/migrations/`. New schema = a new migration with an idempotent
|
|
guard and a real downgrade. Migrations must run clean on strict MySQL 8.
|
|
Any model column/table change ships WITH its migration in the SAME change, and
|
|
bringing up a new image MUST run `flask db upgrade` then
|
|
`flask plugin upgrade-all` before serving traffic. A model that references a
|
|
column its migration has not applied yet 500s every query on that table
|
|
(`1054 Unknown column`), so code and schema must never be deployed out of step.
|
|
- **Asset model is the platform contract.** Physical things are an `Asset` plus a
|
|
plugin subtype row linked by `assetid` (FK, `ON DELETE CASCADE`). Consumables
|
|
with quantities are standalone tables, not assets.
|
|
- **Ledger pattern**: a cached `quantityonhand` moves in the SAME commit as the
|
|
signed transaction row it reflects.
|
|
- **Configuration for endpoint agent**: The endpoint agent's live collector key and base URL are provisioned in the Windows registry `HKLM\SOFTWARE\GE\ShopDB` (values `CollectorKey`, `BaseUrl`), not committed in `appsettings.json`; `appsettings.json` holds only non-secret runtime settings.
|
|
|
|
## Before you finish a change
|
|
|
|
Run the three gates (CI runs the same):
|
|
|
|
```
|
|
python -m pytest tests/ -q
|
|
cd frontend && npx vitest run && npm run build && cd ..
|
|
bash scripts/check-naming-and-style.sh
|
|
```
|
|
|
|
Commits: short present-tense subject, body says WHY. No AI/tool attribution in
|
|
commit messages, code comments, or docs.
|