Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/apps/crm.app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ export const CrmApp = App.create({
children: [
{ id: 'nav_lead', type: 'object', objectName: 'crm_lead', label: 'Leads', icon: 'user-plus' },
{ id: 'nav_account', type: 'object', objectName: 'crm_account', label: 'Accounts', icon: 'building' },
// ADR-0047 interface page — the curated counterpart to the Accounts
// object entry (quick filters only; activates with spec > 9.2.0).
{ id: 'nav_account_workbench', type: 'page', pageName: 'account_workbench', label: 'Account Workbench', icon: 'sliders-horizontal' },
{ id: 'nav_contact', type: 'object', objectName: 'crm_contact', label: 'Contacts', icon: 'user' },
{ id: 'nav_opportunity', type: 'object', objectName: 'crm_opportunity', label: 'Opportunities', icon: 'target' },
{ id: 'nav_pipeline', type: 'object', objectName: 'crm_opportunity', viewName: 'pipeline_kanban', label: 'Pipeline', icon: 'columns-3' },
Expand Down
71 changes: 71 additions & 0 deletions src/pages/account_workbench.page.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.

import { Page } from '@objectstack/spec/ui';

/**
* Account Workbench — ADR-0047 interface page (Airtable Interfaces parity).
*
* The author-curated counterpart to the Accounts object nav entry. Where
* the object entry (data mode) shows every list view as switcher tabs and
* offers the full toolbar, this page is deliberately closed:
*
* • it REFERENCES the account default view (`sourceView`) — columns,
* base filter and sort are inherited, never restated (the iron rule);
* • end users get exactly three quick filters: industry (with record
* counts), customer type, and owner (a user lookup — renders as a
* record-picker dropdown);
* • the visualization is locked to grid (single-entry whitelist);
* • advanced filtering / view management are not offered.
*
* Filter selections persist as `uf_*` URL params — reload-safe, shareable.
*
* NOTE: `interfaceConfig.userFilters` requires @objectstack/spec > 9.2.0
* (ADR-0047). On older specs defineStack strips the unknown keys and the
* page renders without the filter bar — a harmless no-op until the
* dependency bump activates it.
*/
export const AccountWorkbenchPage: Page = {
name: 'account_workbench',
label: 'Account Workbench',
description: 'Curated account list for the sales team: quick filters only, no view management.',
type: 'list',
object: 'crm_account',
kind: 'full',
template: 'default',
isDefault: false,
// Interface pages carry no regions — the list surface is generated from
// `interfaceConfig` (ADR-0047), not composed from components.
regions: [],
interfaceConfig: {
source: 'crm_account',
sourceView: 'all_accounts',

...({
userFilters: {
element: 'dropdown',
fields: [
{ field: 'industry', showCount: true },
{ field: 'type' },
{ field: 'owner' },
],
},
// typed via spread-as-any until @objectstack/spec ships ADR-0047
// (UserFiltersSchema is in framework main, > 9.2.0)
} as any),

appearance: {
showDescription: true,
allowedVisualizations: ['grid'],
},

userActions: {
sort: true,
search: true,
filter: false,
rowHeight: false,
addRecordForm: false,
},

showRecordCount: true,
},
};
1 change: 1 addition & 0 deletions src/pages/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
export { LeadDetailPage } from './lead_detail.page';
export { OpportunityDetailPage } from './opportunity_detail.page';
export { AccountDetailPage } from './account_detail.page';
export { AccountWorkbenchPage } from './account_workbench.page';
export { CaseDetailPage } from './case_detail.page';
export { SalesHomePage } from './home.page';
export { AppLauncherPage } from './app_launcher.page';
Expand Down
20 changes: 20 additions & 0 deletions src/views/account.view.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,26 @@ export const AccountViews = defineView({
columns: ['name', 'industry', 'annual_revenue', 'number_of_employees', 'owner'],
filter: [{ field: 'annual_revenue', operator: 'greater_than_or_equal', value: 10000000 }],
sort: [{ field: 'annual_revenue', order: 'desc' }],

// ADR-0047 end-user quick filters (Airtable "User filters", Elements:
// dropdowns). Lives on THIS view, not the default one: the default
// view's `tabs` act as the view switcher, and filter tabs/dropdowns
// are mutually exclusive with a tab row on the same toolbar.
// `owner` is a user lookup — it renders as a record-picker dropdown.
// NOTE: requires @objectstack/spec > 9.2.0 (ADR-0047 UserFiltersSchema);
// on older specs defineStack strips this block — harmless no-op.
...({
userFilters: {
element: 'dropdown',
fields: [
{ field: 'industry', showCount: true },
{ field: 'type' },
{ field: 'owner' },
],
},
// typed via spread-as-any until @objectstack/spec ships ADR-0047
// (UserFiltersSchema is in framework main, > 9.2.0)
} as any),
},

my_accounts: {
Expand Down
Loading