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
13 changes: 13 additions & 0 deletions .changeset/dead-form-data-provider.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
'hotcrm': patch
---

Remove the `form.data` provider from all twelve view files. A form binds to its
object and record through the route context, so the block never wired anything —
the platform's own `liveness-dead-property` rule flagged every one of them.
Verified before removal, not taken on the validator's word: with the blocks gone,
a lead record's edit form still binds on 16.1.0 (8 inputs, 7 populated from the
record). Adds two guards — no view may reintroduce `form.data`, and every view
must still resolve its object from the list provider now that the `form.data`
fallback is gone. Clears the last 12 validate warnings; `pnpm verify` goes from
15 warnings to 3 (all pre-existing).
1 change: 0 additions & 1 deletion src/views/account.view.ts
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,6 @@ export const AccountViews = defineView({

form: {
type: 'tabbed',
data: { provider: 'object', object: 'crm_account' },
sections: [
{
label: 'Profile',
Expand Down
1 change: 0 additions & 1 deletion src/views/campaign.view.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,6 @@ export const CampaignViews = defineView({

form: {
type: 'tabbed',
data: { provider: 'object', object: 'crm_campaign' },
sections: [
{
label: 'Overview',
Expand Down
1 change: 0 additions & 1 deletion src/views/case.view.ts
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,6 @@ export const CaseViews = defineView({

form: {
type: 'tabbed',
data: { provider: 'object', object: 'crm_case' },
sections: [
{
label: 'Case',
Expand Down
1 change: 0 additions & 1 deletion src/views/contact.view.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,6 @@ export const ContactViews = defineView({

form: {
type: 'tabbed',
data: { provider: 'object', object: 'crm_contact' },
sections: [
{
label: 'Identity',
Expand Down
1 change: 0 additions & 1 deletion src/views/contract.view.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,6 @@ export const ContractViews = defineView({

form: {
type: 'tabbed',
data: { provider: 'object', object: 'crm_contract' },
sections: [
{
label: 'Parties',
Expand Down
1 change: 0 additions & 1 deletion src/views/forecast.view.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,6 @@ export const ForecastViews = defineView({

form: {
type: 'simple',
data: { provider: 'object', object: 'crm_forecast' },
sections: [
{
label: 'Snapshot',
Expand Down
1 change: 0 additions & 1 deletion src/views/knowledge_article.view.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,6 @@ export const KnowledgeArticleViews = defineView({

form: {
type: 'simple',
data: { provider: 'object', object: 'crm_knowledge_article' },
sections: [
{
label: 'Article',
Expand Down
8 changes: 0 additions & 8 deletions src/views/lead.view.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,10 +113,6 @@ export const LeadViews = defineView({
*/
form: {
type: 'simple',
data: {
provider: 'object',
object: 'crm_lead',
},

sections: [
{
Expand Down Expand Up @@ -401,10 +397,6 @@ export const LeadViews = defineView({
*/
detail_form: {
type: 'tabbed',
data: {
provider: 'object',
object: 'crm_lead',
},
sections: [
{
label: 'General',
Expand Down
1 change: 0 additions & 1 deletion src/views/opportunity.view.ts
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,6 @@ export const OpportunityViews = defineView({

form: {
type: 'tabbed',
data: { provider: 'object', object: 'crm_opportunity' },
sections: [
{
label: 'Overview',
Expand Down
1 change: 0 additions & 1 deletion src/views/product.view.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,6 @@ export const ProductViews = defineView({

form: {
type: 'simple',
data: { provider: 'object', object: 'crm_product' },
sections: [
{
label: 'Product Info',
Expand Down
1 change: 0 additions & 1 deletion src/views/quote.view.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,6 @@ export const QuoteViews = defineView({

form: {
type: 'tabbed',
data: { provider: 'object', object: 'crm_quote' },
sections: [
{
label: 'Quote',
Expand Down
1 change: 0 additions & 1 deletion src/views/task.view.ts
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,6 @@ export const TaskViews = defineView({

form: {
type: 'simple',
data: { provider: 'object', object: 'crm_task' },
sections: [
{
label: 'Task',
Expand Down
45 changes: 45 additions & 0 deletions test/metadata-references.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1105,3 +1105,48 @@ describe('action labels are translated in every locale', () => {
expect(bad, `action strings declared in code but not translated:\n ${bad.join('\n ')}`).toEqual([]);
});
});

/**
* `form.data` is a data provider the form renderer never reads: a form binds to
* its object and record through the route context, so the block only *looked*
* like it was wiring the form to an object. The platform's own liveness rule
* (`liveness-dead-property`) flagged twelve of them, one per view file.
*
* Verified before removing them, rather than taken on the validator's word —
* the same validator reports false positives elsewhere (it cannot see view
* names inside the twelve grouped `views` exports, so it calls live routes
* dead). With every `form.data` deleted, opening a lead record's edit form on
* 16.1.0 still binds correctly: 8 inputs, 7 populated from the record
* (`first_name: "Mira"`, `company: "Atlas Construction"`, `status: "contacted"`,
* …), no console errors.
*
* Scope note: named forms under `formViews` (`quick_create`,
* `lead_conversion_wizard`, …) still carry `data` blocks. The liveness rule does
* NOT flag those and they have not been measured — a create form has no record
* in the route context, so the same reasoning may not hold. They are left alone
* deliberately; measure first if you plan to remove them.
*/
describe('form views do not declare a dead data provider', () => {
it('no view sets form.data', () => {
const bad: string[] = [];
for (const v of views) {
if (!v.form?.data) continue;
const objectName = v.list?.data?.object ?? v.object ?? '(unknown object)';
bad.push(`${objectName}: form.data = ${JSON.stringify(v.form.data)}`);
}
expect(
bad,
`form.data is not consumed — a form binds via the route context:\n ${bad.join('\n ')}`,
).toEqual([]);
});

it('every view still resolves its object without the form.data fallback', () => {
// objectOf() used to fall back to `form.data.object`. With those blocks gone
// the list provider is the only source, so a view that lost both would make
// every rule keyed on objectOf() silently skip it.
const unresolved = views
.filter((v) => !(v.list?.data?.object ?? v.object))
.map((v) => v.list?.name ?? v.form?.type ?? '(unnamed view)');
expect(unresolved, `views whose object no longer resolves:\n ${unresolved.join('\n ')}`).toEqual([]);
});
});
Loading