Skip to content

Employer views: pipeline kanban, inbox, interview calendar, talent pool - #11

Open
os-sam wants to merge 1 commit into
mainfrom
claude/issue-2-employer-views
Open

Employer views: pipeline kanban, inbox, interview calendar, talent pool#11
os-sam wants to merge 1 commit into
mainfrom
claude/issue-2-employer-views

Conversation

@os-sam

@os-sam os-sam commented Sep 7, 2026

Copy link
Copy Markdown
Collaborator

Fixes #2

What changed

Card 07: four defineView containers under src/views/ (application, interview, candidate, job), the barrel src/views/index.ts, and the views: key in objectstack.config.ts — only that key and its import, since #5 and #6 are editing the same file.

Object Views
ats_application list grid (display_name, job, candidate, stage, source, applied_at, rating) · pipeline kanban groupByField: 'stage', cards display_name / job / rating / applied_at · inbox_new (stage = applied) · inbox_screening · inbox_interview · inbox_offer · inbox_hired · formViews.default two-column (job, candidate, stage, source, rating, cover_letter)
ats_interview list grid (display_name, round, scheduled_at, mode, interviewers, status, rating) · calendar on scheduled_at, title display_name, colour status
ats_candidate talent_pool grid (full_name, city, current_title, experience_years, skills, seeking_status) with userFilters dropdowns on skills / city / experience_years · gallery cover avatar, title full_name, current_title as first visible field
ats_job mine grid (title, status, city, employment_type, headcount, published_at, expires_at) · published = filter status equals 'published'

Every grid offers exportOptions: { formats: ['csv', 'xlsx'] }. Filters are structured ViewFilterRule entries over declared fields — the list-view filter surface is JSON rules, not CEL (objectstack-formula, "Surfaces that take an Expression"), which is why no record. predicate appears here.

Decisions worth a second look:

  • list.name: 'all' on application and interview. The container expander registers an unnamed default list as OBJECT.default — the same key the card pins for formViews.default — and would have renamed the form to default_2 with a collision warning. Naming the list keeps ats_application.default for the form. Verified with expandViewContainerWithDiagnostics on the built artifact: 0 collisions, 14 items, names as listed by GET /api/v1/meta/view.
  • inbox_new filters on stage == 'applied'. stage has no new value (DESIGN.md §02); applied is the entry stage.
  • No scoping filter on mine or the talent pool. Both employer permission sets already scope ats_job by employer_org IN (current_user.accessible_org_ids); a view filter is presentation, not security.
  • Gallery subtitle. GalleryConfigSchema has no subtitle key; current_title is the first visibleFields entry, followed by city and seeking_status.
  • Interview grid adds display_name as the linked first column ahead of the six the card lists.

Gates (all exit 0)

pnpm validate

  → Validating against ObjectStack Protocol...
  → Running author-time rules (42)...
  → Checking capability providers (#3366)...
  → Checking package docs (ADR-0046)...

  ✓ Validation passed (309ms)

  Data: 11 Objects  129 Fields
  UI: 4 Views
  Security: 5 Positions  6 Permissions

pnpm lint

◆ Lint
  → Loading configuration...
  ℹ Config: /home/user/ats-issue-2/objectstack.config.ts

  ✓ All checks passed (204ms)

pnpm typecheck

> ats@0.1.0 typecheck
> tsc --noEmit
(no output, exit 0)

Reverse check, each typo made on top of the committed tree, pnpm validate run, then restored with git checkout HEAD -- and verified byte-identical: column applied_att → exit 1, 6 issues with did-you-mean; kanban.groupByField: 'stag' → exit 1; calendar.startDateField: 'scheduled_att' → exit 1; inbox filter field stag → exit 1, 5 issues (list-view-field-unknown). The gate binds columns, kanban, calendar and filter fields.

Boot and screenshots

os dev --ui --fresh --database-driver memory boots on this branch; GET /api/v1/meta/view lists all 14 expanded views. Console route used: /_console/apps/setup/OBJECT/view/OBJECT.KEY (there is no ATS app until card 09).

Pipeline groups by stage — lanes Applied · Screening · Interview · Offer · Hired, cards carrying display_name / job / rating / applied_at:

Pipeline kanban grouped by stage

Calendar renders on scheduled_at, events titled by display_name:

Interview calendar on scheduled_at

Also captured: inbox_screening · talent_pool with the filter bar · gallery · jobs mine. The PNGs live on the orphan branch claude/issue-2-employer-views-evidence (not for merge; delete after landing — the artifact-page publish was refused by the harness).

Caveat on the rows behind the screenshots. On origin/main the stamp hooks throw under the body-only sandbox (ctx.ql is undefined), so inserting a job, application or interview through REST or the Console answers 500 on an unmodified boot — filed as #10, out of scope for this card. The demo rows were written against a local copy of the built artifact with hooks: [], supplying display_name and employer directly; the views are byte-identical to this branch, only the rows were seeded around the defect. Names and employers in the screenshots are invented.

Not in this PR

🤖 Generated with Claude Code

https://claude.ai/code/session_01PbJ5Cy9KDAzeQHo8bsMadG


Generated by Claude Code

…alent pool

Card 07 (#2). Four defineView containers under src/views/ and the `views:`
key in objectstack.config.ts:

- ats_application: default grid, `pipeline` kanban grouped by `stage`,
  five `inbox_*` grids filtered by stage, a two-column `default` form.
- ats_interview: default grid and a `calendar` on `scheduled_at`, titled by
  the stored `display_name` mirror and coloured by `status`.
- ats_candidate: `talent_pool` grid with a filter bar on skills, city and
  experience_years, and a `gallery` (avatar cover, full_name title).
- ats_job: `mine` and `published` (status == 'published') grids.

Why the shapes are what they are: the container expander names the default
list `<object>.default`, so the application list is named `all` to keep the
`default` key for the form the card pins. `mine` and the talent pool carry
no scoping filter — which rows a caller may read is the permission set's
row-level rule, and a view filter is presentation, not security. The gallery
config has no subtitle key, so `current_title` is the first visible field.
Export menus offer csv and xlsx on every grid.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PbJ5Cy9KDAzeQHo8bsMadG
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Employer views: pipeline kanban, inbox, interview calendar, talent pool

1 participant