@mj-biz-apps/sales-ng 6.7.1 → 6.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/form-panels/deal-form.panels.d.ts +54 -4
- package/dist/lib/form-panels/deal-form.panels.d.ts.map +1 -1
- package/dist/lib/form-panels/deal-form.panels.js +111 -31
- package/dist/lib/form-panels/deal-form.panels.js.map +1 -1
- package/dist/lib/form-panels/deal-line-editor.component.d.ts.map +1 -1
- package/dist/lib/form-panels/deal-line-editor.component.js +56 -5
- package/dist/lib/form-panels/deal-line-editor.component.js.map +1 -1
- package/dist/lib/generated/Entities/mjBizAppsSalesPipeline/mjbizappssalespipeline.form.component.js +31 -29
- package/dist/lib/generated/Entities/mjBizAppsSalesPipeline/mjbizappssalespipeline.form.component.js.map +1 -1
- package/dist/lib/pages/dashboard-dates.d.ts +12 -20
- package/dist/lib/pages/dashboard-dates.d.ts.map +1 -1
- package/dist/lib/pages/dashboard-dates.js +39 -5
- package/dist/lib/pages/dashboard-dates.js.map +1 -1
- package/dist/lib/pages/dashboard-inspect.d.ts +12 -2
- package/dist/lib/pages/dashboard-inspect.d.ts.map +1 -1
- package/dist/lib/pages/dashboard-inspect.js +16 -4
- package/dist/lib/pages/dashboard-inspect.js.map +1 -1
- package/dist/lib/pages/dashboard-period.d.ts +6 -1
- package/dist/lib/pages/dashboard-period.d.ts.map +1 -1
- package/dist/lib/pages/dashboard-period.js +8 -3
- package/dist/lib/pages/dashboard-period.js.map +1 -1
- package/dist/lib/sections/sales-section.component.d.ts +6 -0
- package/dist/lib/sections/sales-section.component.d.ts.map +1 -1
- package/dist/lib/sections/sales-section.component.js +32 -14
- package/dist/lib/sections/sales-section.component.js.map +1 -1
- package/dist/lib/workspace/deal-workspace.component.d.ts +39 -3
- package/dist/lib/workspace/deal-workspace.component.d.ts.map +1 -1
- package/dist/lib/workspace/deal-workspace.component.js +99 -19
- package/dist/lib/workspace/deal-workspace.component.js.map +1 -1
- package/dist/lib/workspace/deal-workspace.dates.d.ts +19 -27
- package/dist/lib/workspace/deal-workspace.dates.d.ts.map +1 -1
- package/dist/lib/workspace/deal-workspace.dates.js +29 -24
- package/dist/lib/workspace/deal-workspace.dates.js.map +1 -1
- package/dist/lib/workspace/deal-workspace.service.d.ts +18 -1
- package/dist/lib/workspace/deal-workspace.service.d.ts.map +1 -1
- package/dist/lib/workspace/deal-workspace.service.js +16 -2
- package/dist/lib/workspace/deal-workspace.service.js.map +1 -1
- package/package.json +4 -3
|
@@ -195,6 +195,48 @@ interface DealFieldSpec {
|
|
|
195
195
|
currency?: boolean;
|
|
196
196
|
}
|
|
197
197
|
export declare class MJSDealOverviewPanel extends BaseFormPanel<DealEntity> {
|
|
198
|
+
/**
|
|
199
|
+
* HAS THE BUSINESS ZONE BEEN LOADED? (bc-aidp-next-golive#168)
|
|
200
|
+
*
|
|
201
|
+
* A SIGNAL, for the reason the Pipeline panel's `statuses` is one: the host is OnPush and nothing
|
|
202
|
+
* marks this panel dirty when `Config()` resolves, so the four getters below would paint their
|
|
203
|
+
* first values from the unconfigured engine and keep them. Read inside {@link daysFromToday},
|
|
204
|
+
* which every one of them goes through, so the template's read of any countdown registers the
|
|
205
|
+
* dependency and re-runs once the zone lands. `inject(ChangeDetectorRef)` would also do it and
|
|
206
|
+
* would cost `new MJSDealOverviewPanel()` in a unit test.
|
|
207
|
+
*
|
|
208
|
+
* `?.()` because the suites construct panels with `Object.create(prototype)`, which runs no field
|
|
209
|
+
* initialisers — an absent signal means "not marked", never a throw out of a template binding.
|
|
210
|
+
*/
|
|
211
|
+
private readonly businessZoneLoaded;
|
|
212
|
+
/**
|
|
213
|
+
* THE ZONE IS LOADED BEFORE THIS PANEL IS ASKED WHAT DAY IT IS (bc-aidp-next-golive#168).
|
|
214
|
+
*
|
|
215
|
+
* `BusinessTimeZoneEngine` FAILS OPEN TO UTC when it has not been configured — that is its
|
|
216
|
+
* documented contract, and it is silently the exact defect #168 exists to fix, so an unconfigured
|
|
217
|
+
* read is not a neutral default but the old close clock wearing the new code. `@RegisterForStartup()`
|
|
218
|
+
* means MJ's boot sequence configures it, but `sales-ng` is a lazily-loaded chunk that a deal form
|
|
219
|
+
* can mount before or without that sequence having run here, and the two other `Today()` call sites
|
|
220
|
+
* in this app (`deal-workspace.service.ts`, `sales-section.component.ts`) already refuse to rely on
|
|
221
|
+
* it. This one was left relying on it.
|
|
222
|
+
*
|
|
223
|
+
* `Config(false)` is idempotent and a no-op once loaded, so mounting the panel costs nothing after
|
|
224
|
+
* the first time, and the engine resolves to UTC rather than throwing when no configuration row
|
|
225
|
+
* exists — a host that has not set a zone behaves exactly as it did before.
|
|
226
|
+
*
|
|
227
|
+
* BaseFormPanel declares no lifecycle hook, so there is nothing to chain to.
|
|
228
|
+
*/
|
|
229
|
+
ngOnInit(): Promise<void>;
|
|
230
|
+
/**
|
|
231
|
+
* {@link daysFrom}, read through the load signal above.
|
|
232
|
+
*
|
|
233
|
+
* Every today-relative getter on this panel goes through here rather than calling `daysFrom`
|
|
234
|
+
* directly, so there is ONE place that both marks the zone dependency and can be pointed at when
|
|
235
|
+
* asking "what configured the engine for this figure?" — a second call site that skipped it would
|
|
236
|
+
* paint a UTC countdown next to a business-day one on the same tile, which is the disagreement
|
|
237
|
+
* #168 was filed about in the first place.
|
|
238
|
+
*/
|
|
239
|
+
private daysFromToday;
|
|
198
240
|
G(field: string): string;
|
|
199
241
|
get Money(): string;
|
|
200
242
|
get Weighted(): string;
|
|
@@ -654,10 +696,18 @@ export declare class MJSDealClosePanel extends MJSDealFieldPanel {
|
|
|
654
696
|
* The audited way back through the lock (bc-aidp-next-golive#205).
|
|
655
697
|
*
|
|
656
698
|
* Mirrors {@link ConfirmClose}, including the part that is easy to drop: a reopen can return
|
|
657
|
-
* `Success: true` WITH issues, and those are the ones that matter most.
|
|
658
|
-
*
|
|
659
|
-
*
|
|
660
|
-
*
|
|
699
|
+
* `Success: true` WITH issues, and those are the ones that matter most. The deal reopens
|
|
700
|
+
* regardless of what the order does, because an order-side refusal must never block a stage
|
|
701
|
+
* change — so this list is the only thing standing between the rep and a live deal pointing at a
|
|
702
|
+
* dead order.
|
|
703
|
+
*
|
|
704
|
+
* THIS USED TO SAY the reopen "asks the order to come back while it sits at `Voided`, which orders
|
|
705
|
+
* treats as terminal". It does not: `TRANSITIONS.Voided` is `['Draft', 'Quoted']`, so
|
|
706
|
+
* `IsTerminal('Voided')` is FALSE and `Confirmed` is the terminal status. Recorded once in
|
|
707
|
+
* `docs/DECISIONS.md` D-OS4; KI-27 is the lifecycle collapse that caused it, not the transition
|
|
708
|
+
* fact itself. The cases that genuinely leave an order behind are a BOOKED order, which the reopen
|
|
709
|
+
* refuses outright, and — until golive#205 — a restored stage that declared nothing, which asked
|
|
710
|
+
* the order for nothing and said nothing either.
|
|
661
711
|
*
|
|
662
712
|
* IT DOES SAVE FIRST, which this comment used to say it must not. The old reasoning was that "a
|
|
663
713
|
* locked deal has almost nothing editable, and the close lock would refuse the save anyway". Both
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"deal-form.panels.d.ts","sourceRoot":"","sources":["../../../src/lib/form-panels/deal-form.panels.ts"],"names":[],"mappings":"AAgBA,OAAO,EAAmC,KAAK,UAAU,EAAqB,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"deal-form.panels.d.ts","sourceRoot":"","sources":["../../../src/lib/form-panels/deal-form.panels.ts"],"names":[],"mappings":"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"}
|
|
@@ -22,6 +22,7 @@ import { CommonModule } from '@angular/common';
|
|
|
22
22
|
import { FormsModule } from '@angular/forms';
|
|
23
23
|
import { CompositeKey, Metadata, RunView, EntitySaveOptions } from '@memberjunction/core';
|
|
24
24
|
import { RegisterClassEx } from '@memberjunction/global';
|
|
25
|
+
import { BusinessTimeZoneEngine, FromCalendarDay, ToCalendarDay } from '@mj-biz-apps/common-entities';
|
|
25
26
|
import { BaseFormPanel, BaseFormsModule, ExplorerEntityDataGridComponent } from '@memberjunction/ng-base-forms';
|
|
26
27
|
import { EntityViewerModule, } from '@memberjunction/ng-entity-viewer';
|
|
27
28
|
import { IsDealFieldEditableWhileLocked, LoadDealStatusOptions, } from '@mj-biz-apps/sales-entities';
|
|
@@ -1048,7 +1049,7 @@ async function LoadLossReasons() {
|
|
|
1048
1049
|
*
|
|
1049
1050
|
* TWO LAYERS OF SUCCESS. `Success` on the envelope means the operation RAN; whether the deal reopened
|
|
1050
1051
|
* is `Output.Success`. And a SUCCESSFUL reopen still carries issues worth showing: S-US8 reopens behind
|
|
1051
|
-
* an order
|
|
1052
|
+
* an order the deal cannot be worked from, and that list is the only thing between the rep and a live deal
|
|
1052
1053
|
* pointing at a dead order.
|
|
1053
1054
|
*/
|
|
1054
1055
|
/**
|
|
@@ -1229,18 +1230,41 @@ function moneyExact(n) {
|
|
|
1229
1230
|
style: 'currency', currency: 'USD', minimumFractionDigits: 2, maximumFractionDigits: 2,
|
|
1230
1231
|
});
|
|
1231
1232
|
}
|
|
1233
|
+
/**
|
|
1234
|
+
* Whole days from TODAY to a stored day. Negative is in the past.
|
|
1235
|
+
*
|
|
1236
|
+
* ── TWO READS, AND ONLY ONE OF THEM HAS A ZONE (bc-aidp-next-golive#168) ────────────────────────
|
|
1237
|
+
*
|
|
1238
|
+
* The STORED side is a `DATE` column — a calendar day with no time and no zone, handed back as UTC
|
|
1239
|
+
* midnight — so `ToCalendarDay` reads it from UTC parts and takes a string as written. That half was
|
|
1240
|
+
* always right and has not moved.
|
|
1241
|
+
*
|
|
1242
|
+
* TODAY is the half that was wrong. It read `now.getUTC*()`, so the countdown rolled over at UTC
|
|
1243
|
+
* midnight: from 19:00 Central every close clock, every "overdue" verdict and the next-step warning
|
|
1244
|
+
* jumped a day early. A deal closing tomorrow read "today" all evening, and after #168 fixed the
|
|
1245
|
+
* product picker the same screen carried two different ideas of what day it was.
|
|
1246
|
+
*
|
|
1247
|
+
* SYNCHRONOUS, like the getters that call it — so IT DOES NOT CONFIGURE THE ENGINE, and must never be
|
|
1248
|
+
* reached before something else has. `MJSDealOverviewPanel.ngOnInit` is that something else, and
|
|
1249
|
+
* {@link MJSDealOverviewPanel.daysFromToday} is the only way in; call this directly from a new panel
|
|
1250
|
+
* and you get UTC.
|
|
1251
|
+
*
|
|
1252
|
+
* The reasoning this replaces said `@RegisterForStartup()` made the boot sequence enough, and that the
|
|
1253
|
+
* UTC fallback made the worst case harmless. Both halves were wrong together: `sales-ng` is a lazily
|
|
1254
|
+
* loaded chunk, and the UTC fallback IS the defect #168 fixes — falling open to it here restores the
|
|
1255
|
+
* old close clock silently, with one logged warning nobody reads. Failing open is still the right
|
|
1256
|
+
* contract (a date default that throws out of a template binding is worse), which is exactly why the
|
|
1257
|
+
* `Config()` has to be arranged for rather than assumed.
|
|
1258
|
+
*
|
|
1259
|
+
* Both sides are converted through `FromCalendarDay`, i.e. UTC midnight, so the subtraction is whole
|
|
1260
|
+
* days with no DST remainder to round away. `Math.round` is kept as a belt on that brace.
|
|
1261
|
+
*/
|
|
1232
1262
|
function daysFrom(d) {
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
const iso = d instanceof Date
|
|
1236
|
-
? `${d.getUTCFullYear()}-${String(d.getUTCMonth() + 1).padStart(2, '0')}-${String(d.getUTCDate()).padStart(2, '0')}`
|
|
1237
|
-
: String(d).slice(0, 10);
|
|
1238
|
-
const t = Date.parse(`${iso}T00:00:00Z`);
|
|
1239
|
-
if (!Number.isFinite(t))
|
|
1263
|
+
const day = ToCalendarDay(d);
|
|
1264
|
+
if (day === null)
|
|
1240
1265
|
return null;
|
|
1241
|
-
const
|
|
1242
|
-
|
|
1243
|
-
return Math.round((t - today) / 86_400_000);
|
|
1266
|
+
const today = BusinessTimeZoneEngine.Instance.Today();
|
|
1267
|
+
return Math.round((FromCalendarDay(day).getTime() - FromCalendarDay(today).getTime()) / 86_400_000);
|
|
1244
1268
|
}
|
|
1245
1269
|
/**
|
|
1246
1270
|
* Whole days from one date to another, both read as UTC days.
|
|
@@ -1567,6 +1591,54 @@ const FIELD_STYLES = `
|
|
|
1567
1591
|
`;
|
|
1568
1592
|
/* ── Overview ─────────────────────────────────────────────────────────────── */
|
|
1569
1593
|
let MJSDealOverviewPanel = class MJSDealOverviewPanel extends BaseFormPanel {
|
|
1594
|
+
/**
|
|
1595
|
+
* HAS THE BUSINESS ZONE BEEN LOADED? (bc-aidp-next-golive#168)
|
|
1596
|
+
*
|
|
1597
|
+
* A SIGNAL, for the reason the Pipeline panel's `statuses` is one: the host is OnPush and nothing
|
|
1598
|
+
* marks this panel dirty when `Config()` resolves, so the four getters below would paint their
|
|
1599
|
+
* first values from the unconfigured engine and keep them. Read inside {@link daysFromToday},
|
|
1600
|
+
* which every one of them goes through, so the template's read of any countdown registers the
|
|
1601
|
+
* dependency and re-runs once the zone lands. `inject(ChangeDetectorRef)` would also do it and
|
|
1602
|
+
* would cost `new MJSDealOverviewPanel()` in a unit test.
|
|
1603
|
+
*
|
|
1604
|
+
* `?.()` because the suites construct panels with `Object.create(prototype)`, which runs no field
|
|
1605
|
+
* initialisers — an absent signal means "not marked", never a throw out of a template binding.
|
|
1606
|
+
*/
|
|
1607
|
+
businessZoneLoaded = signal(false, ...(ngDevMode ? [{ debugName: "businessZoneLoaded" }] : []));
|
|
1608
|
+
/**
|
|
1609
|
+
* THE ZONE IS LOADED BEFORE THIS PANEL IS ASKED WHAT DAY IT IS (bc-aidp-next-golive#168).
|
|
1610
|
+
*
|
|
1611
|
+
* `BusinessTimeZoneEngine` FAILS OPEN TO UTC when it has not been configured — that is its
|
|
1612
|
+
* documented contract, and it is silently the exact defect #168 exists to fix, so an unconfigured
|
|
1613
|
+
* read is not a neutral default but the old close clock wearing the new code. `@RegisterForStartup()`
|
|
1614
|
+
* means MJ's boot sequence configures it, but `sales-ng` is a lazily-loaded chunk that a deal form
|
|
1615
|
+
* can mount before or without that sequence having run here, and the two other `Today()` call sites
|
|
1616
|
+
* in this app (`deal-workspace.service.ts`, `sales-section.component.ts`) already refuse to rely on
|
|
1617
|
+
* it. This one was left relying on it.
|
|
1618
|
+
*
|
|
1619
|
+
* `Config(false)` is idempotent and a no-op once loaded, so mounting the panel costs nothing after
|
|
1620
|
+
* the first time, and the engine resolves to UTC rather than throwing when no configuration row
|
|
1621
|
+
* exists — a host that has not set a zone behaves exactly as it did before.
|
|
1622
|
+
*
|
|
1623
|
+
* BaseFormPanel declares no lifecycle hook, so there is nothing to chain to.
|
|
1624
|
+
*/
|
|
1625
|
+
async ngOnInit() {
|
|
1626
|
+
await BusinessTimeZoneEngine.Instance.Config(false);
|
|
1627
|
+
this.businessZoneLoaded.set(true);
|
|
1628
|
+
}
|
|
1629
|
+
/**
|
|
1630
|
+
* {@link daysFrom}, read through the load signal above.
|
|
1631
|
+
*
|
|
1632
|
+
* Every today-relative getter on this panel goes through here rather than calling `daysFrom`
|
|
1633
|
+
* directly, so there is ONE place that both marks the zone dependency and can be pointed at when
|
|
1634
|
+
* asking "what configured the engine for this figure?" — a second call site that skipped it would
|
|
1635
|
+
* paint a UTC countdown next to a business-day one on the same tile, which is the disagreement
|
|
1636
|
+
* #168 was filed about in the first place.
|
|
1637
|
+
*/
|
|
1638
|
+
daysFromToday(d) {
|
|
1639
|
+
this.businessZoneLoaded?.();
|
|
1640
|
+
return daysFrom(d);
|
|
1641
|
+
}
|
|
1570
1642
|
G(field) {
|
|
1571
1643
|
const v = this.Record?.Get?.(field);
|
|
1572
1644
|
return v == null || v === '' ? '' : String(v);
|
|
@@ -1603,7 +1675,7 @@ let MJSDealOverviewPanel = class MJSDealOverviewPanel extends BaseFormPanel {
|
|
|
1603
1675
|
* a claim about a caller that no longer exists, and the next reader has no way to tell.
|
|
1604
1676
|
*/
|
|
1605
1677
|
get DaysToCloseLabel() {
|
|
1606
|
-
const n =
|
|
1678
|
+
const n = this.daysFromToday(this.Record?.ExpectedCloseDate);
|
|
1607
1679
|
if (n === null)
|
|
1608
1680
|
return '—';
|
|
1609
1681
|
if (n < 0)
|
|
@@ -1633,7 +1705,7 @@ let MJSDealOverviewPanel = class MJSDealOverviewPanel extends BaseFormPanel {
|
|
|
1633
1705
|
return String(this.Record?.Get?.('ForecastCategoryType') ?? '') || '—';
|
|
1634
1706
|
}
|
|
1635
1707
|
get CloseClock() {
|
|
1636
|
-
const n =
|
|
1708
|
+
const n = this.daysFromToday(this.Record?.ExpectedCloseDate);
|
|
1637
1709
|
// A closed deal shows WHEN it closed. Counting days against an expected date it already met
|
|
1638
1710
|
// (or missed) is advice on a decision nobody can take any more.
|
|
1639
1711
|
if (this.IsClosed) {
|
|
@@ -1762,7 +1834,7 @@ let MJSDealOverviewPanel = class MJSDealOverviewPanel extends BaseFormPanel {
|
|
|
1762
1834
|
// Nothing is overdue on a deal that is finished.
|
|
1763
1835
|
if (this.IsClosed)
|
|
1764
1836
|
return false;
|
|
1765
|
-
const n =
|
|
1837
|
+
const n = this.daysFromToday(this.Record?.NextStepDate);
|
|
1766
1838
|
return n !== null && n < 0;
|
|
1767
1839
|
}
|
|
1768
1840
|
get Health() {
|
|
@@ -1779,7 +1851,7 @@ let MJSDealOverviewPanel = class MJSDealOverviewPanel extends BaseFormPanel {
|
|
|
1779
1851
|
// that is finished -- re-date it, assign it, give it a next step -- and none of it applies.
|
|
1780
1852
|
if (this.IsClosed)
|
|
1781
1853
|
return out;
|
|
1782
|
-
const days =
|
|
1854
|
+
const days = this.daysFromToday(this.Record.ExpectedCloseDate);
|
|
1783
1855
|
if (days !== null && days < 0 && !this.Record.ActualCloseDate) {
|
|
1784
1856
|
out.push('The expected close date has passed. Update the date or close the deal.');
|
|
1785
1857
|
}
|
|
@@ -1990,7 +2062,7 @@ export { MJSDealOverviewPanel };
|
|
|
1990
2062
|
</mj-collapsible-panel>
|
|
1991
2063
|
`, styles: ["\n .mjs-ov { display: flex; flex-direction: column; gap: var(--mj-space-4); padding: var(--mj-space-3) var(--mj-space-4) var(--mj-space-5); }\n .mjs-ov-health { display: flex; flex-direction: column; gap: var(--mj-space-2); }\n .mjs-ov-alert {\n display: flex; align-items: center; gap: var(--mj-space-2);\n padding: var(--mj-space-2) var(--mj-space-3);\n background: var(--mj-status-warning-bg); color: var(--mj-status-warning-text);\n border-radius: var(--mj-radius-md); font-size: var(--mj-text-sm); font-weight: 600;\n }\n .mjs-ov-ok {\n display: flex; align-items: center; gap: var(--mj-space-2);\n padding: var(--mj-space-2) var(--mj-space-3);\n background: var(--mj-status-success-bg); color: var(--mj-status-success-text);\n border-radius: var(--mj-radius-md); font-size: var(--mj-text-sm); font-weight: 600;\n }\n .mjs-ov-strip {\n display: grid; grid-template-columns: repeat(4, minmax(0, 1fr));\n gap: var(--mj-space-3);\n }\n @media (max-width: 900px) { .mjs-ov-strip { grid-template-columns: 1fr 1fr; } }\n .mjs-ov-kpi {\n background: var(--mj-bg-page); border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md); padding: var(--mj-space-3) var(--mj-space-4);\n }\n .mjs-ov-kpi .l {\n font-size: var(--mj-text-xs); text-transform: uppercase; letter-spacing: .04em;\n color: var(--mj-text-muted); font-weight: 700;\n }\n .mjs-ov-kpi .v { font-size: 1.35rem; font-weight: 800; letter-spacing: -.02em; margin-top: 4px; line-height: 1.2; }\n .mjs-ov-kpi .s { color: var(--mj-text-muted); font-size: var(--mj-text-sm); margin-top: 2px; }\n .mjs-ov-kpi[data-tone='warning'] .v { color: var(--mj-status-warning-text); }\n .mjs-ov-kpi[data-tone='success'] .v { color: var(--mj-status-success-text); }\n .mjs-ov-grid { display: grid; grid-template-columns: 1fr 1fr; gap: var(--mj-space-3); }\n @media (max-width: 800px) { .mjs-ov-grid { grid-template-columns: 1fr; } }\n .mjs-ov-card {\n background: var(--mj-bg-page); border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md); padding: var(--mj-space-3) var(--mj-space-4);\n }\n .mjs-ov-card--wide { grid-column: 1 / -1; }\n .mjs-ov-card header {\n display: flex; align-items: center; gap: 8px;\n font-weight: 700; margin-bottom: var(--mj-space-3); color: var(--mj-text-primary);\n }\n .mjs-ov-card header i { color: var(--mj-brand-primary); width: 1.1rem; text-align: center; }\n .mjs-ov-facts { display: grid; grid-template-columns: 1fr 1fr; gap: var(--mj-space-3); }\n .mjs-ov-facts .l {\n font-size: var(--mj-text-xs); text-transform: uppercase; letter-spacing: .04em;\n color: var(--mj-text-muted); font-weight: 700;\n }\n .mjs-ov-facts .v { font-weight: 650; margin-top: 2px; }\n /* The loss reason carries free-text notes under it, so it takes the full row rather than\n squeezing a sentence into a half-width cell. */\n .mjs-ov-fact--span { grid-column: 1 / -1; }\n .mjs-ov-fact--span .s {\n margin-top: 2px; font-weight: 450; color: var(--mj-text-muted);\n white-space: pre-wrap; overflow-wrap: anywhere;\n }\n .mjs-ov-link {\n border: 0; padding: 0; background: transparent; color: var(--mj-text-link);\n cursor: pointer; font: inherit; font-weight: 650; text-align: left;\n }\n .mjs-ov-link:hover { text-decoration: underline; }\n .mjs-ov-next { margin: 0; font-size: 1.05rem; font-weight: 650; }\n .mjs-ov-empty, .muted { color: var(--mj-text-muted); margin: 0; }\n "] }]
|
|
1992
2064
|
}], null, null); })();
|
|
1993
|
-
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MJSDealOverviewPanel, { className: "MJSDealOverviewPanel", filePath: "lib/form-panels/deal-form.panels.ts", lineNumber:
|
|
2065
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MJSDealOverviewPanel, { className: "MJSDealOverviewPanel", filePath: "lib/form-panels/deal-form.panels.ts", lineNumber: 958 }); })();
|
|
1994
2066
|
/* ── Field sections ───────────────────────────────────────────────────────── */
|
|
1995
2067
|
let MJSDealPipelinePanel = class MJSDealPipelinePanel extends MJSDealFieldPanel {
|
|
1996
2068
|
/** Every active status, loaded once. Filtered for display; see SelectableStatuses. */
|
|
@@ -2569,7 +2641,7 @@ export { MJSDealPipelinePanel };
|
|
|
2569
2641
|
</mj-collapsible-panel>
|
|
2570
2642
|
`, styles: ["\n .mjs-fields {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: var(--mj-space-4) var(--mj-space-5);\n padding: var(--mj-space-4) var(--mj-space-5);\n }\n @media (max-width: 720px) { .mjs-fields { grid-template-columns: 1fr; } }\n .mjs-field { min-width: 0; }\n .mjs-field--span { grid-column: 1 / -1; }\n /* The Status control's hints. Previously dw-field__hint, which is defined only in the deal\n WORKSPACE's stylesheet under emulated encapsulation, so the rule could never match markup in\n this component and both hints rendered as unstyled body text. FIELD_STYLES is a template\n literal, so no backticks in here. */\n .mjs-field__hint { display: block; margin-top: var(--mj-space-1); color: var(--mj-text-muted); font-size: 0.78rem; }\n .mjs-reopen { display: flex; flex-direction: column; gap: var(--mj-space-2); margin-top: var(--mj-space-2); }\n .mjs-reopen__field { display: flex; flex-direction: column; gap: var(--mj-space-1); font-size: 0.82rem; }\n .mjs-reopen__field textarea { width: 100%; font: inherit; }\n .mjs-reopen__row { display: flex; gap: var(--mj-space-2); }\n .mjs-reopen__confirm {\n border: 1px solid var(--mj-brand-primary); background: var(--mj-brand-primary);\n color: var(--mj-text-on-brand); border-radius: var(--mj-radius-sm);\n padding: var(--mj-space-1) var(--mj-space-3); cursor: pointer; font: inherit;\n }\n .mjs-reopen__confirm:disabled { opacity: 0.55; cursor: not-allowed; }\n .mjs-reopen__cancel {\n border: 1px solid var(--mj-border-default); background: transparent; color: var(--mj-text-default);\n border-radius: var(--mj-radius-sm); padding: var(--mj-space-1) var(--mj-space-3); cursor: pointer; font: inherit;\n }\n .mjs-reopen__msg { font-size: 0.82rem; color: var(--mj-status-success); }\n .mjs-reopen__msg.is-error { color: var(--mj-status-warning); font-weight: 500; }\n .mjs-reopen__issue { font-size: 0.78rem; color: var(--mj-status-warning); }\n .mjs-field .mj-forms-field {\n display: flex; flex-direction: column; align-items: stretch; gap: 4px; padding: 0;\n }\n .mjs-field .mj-forms-field-label {\n font-size: var(--mj-text-xs); font-weight: 700; letter-spacing: .06em;\n text-transform: uppercase; color: var(--mj-text-muted);\n }\n .mjs-field .mj-forms-field--editing:hover { margin: 0; padding: 0; }\n /* The NATIVE selects this file draws itself, brought into line with the shared control\n (bc-aidp-next-golive#259 item 2: \"Status drop-down list does not seem to be styled consistently\n with rest of the app (shorter font)\").\n\n IT IS A NATIVE SELECT ON PURPOSE. mj-form-field renders a foreign key as an unfiltered dropdown\n off the related entity, which offered Won and Lost and bypassed the audited close -- golive#205,\n and the comment at the Status control says so. Opting out of the component meant opting out of\n its CSS too, and nothing put that back: a bare select inherits the browser's own font, about a\n point smaller than everything around it, which is exactly what was reported.\n\n So this restates .mj-forms-field-input's typography and underline rather than swapping the\n control back. The values are copied from that rule deliberately -- there is no shared token for\n \"a form control\" to reference, and inventing one here would be this app's guess at a platform\n decision.\n\n NO appearance: none. The shared control is a div that draws its own chevron; a native select\n stripped of its appearance would lose the arrow and have nothing to replace it, which is a worse\n inconsistency than the one being fixed.\n\n Scoped to this file's own classes because encapsulation is None on every panel that uses these\n styles, so an unscoped bare-element rule would reach the whole application. All three selects the\n deal form owns -- Status, and the loss reason on the pipeline and close panels -- sit inside one\n of these two. */\n .mjs-field select, .mjs-reopen__field select {\n font-size: 14px; font-family: inherit; color: var(--mj-text-primary);\n background: transparent; border: none;\n border-bottom: 1.5px solid var(--mj-border-default);\n padding: 4px 0; width: 100%; cursor: pointer; outline: none;\n transition: border-color var(--mj-transition-base) ease,\n background var(--mj-transition-base) ease;\n }\n .mjs-field select:focus, .mjs-reopen__field select:focus {\n border-bottom-color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, transparent);\n border-radius: 4px 4px 0 0; padding: 4px 6px;\n }\n /* Matches .mj-forms-field--readonly, which is how the shared control shows a field it will not\n let you change -- the Status select is disabled whenever the deal is locked. */\n .mjs-field select:disabled, .mjs-reopen__field select:disabled {\n opacity: 0.7; cursor: not-allowed;\n }\n /* A money field the panel drew itself. It carries .mj-forms-field-value too, so the size, colour\n and row height are the shared control's rather than a second opinion about them; this adds only\n what money specifically wants -- figures of equal width, so a column of amounts lines up. */\n .mjs-field__money { font-variant-numeric: tabular-nums; }\n"] }]
|
|
2571
2643
|
}], null, null); })();
|
|
2572
|
-
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MJSDealPipelinePanel, { className: "MJSDealPipelinePanel", filePath: "lib/form-panels/deal-form.panels.ts", lineNumber:
|
|
2644
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MJSDealPipelinePanel, { className: "MJSDealPipelinePanel", filePath: "lib/form-panels/deal-form.panels.ts", lineNumber: 1410 }); })();
|
|
2573
2645
|
const PIPELINE_FIELDS = [
|
|
2574
2646
|
// Name and DealNumber are deliberately NOT here. The hero directly above this panel already
|
|
2575
2647
|
// renders Name as an editable field in edit mode, and shows DealNumber beneath the title once
|
|
@@ -2644,7 +2716,7 @@ export { MJSDealPartyPanel };
|
|
|
2644
2716
|
</mj-collapsible-panel>
|
|
2645
2717
|
`, styles: ["\n .mjs-fields {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: var(--mj-space-4) var(--mj-space-5);\n padding: var(--mj-space-4) var(--mj-space-5);\n }\n @media (max-width: 720px) { .mjs-fields { grid-template-columns: 1fr; } }\n .mjs-field { min-width: 0; }\n .mjs-field--span { grid-column: 1 / -1; }\n /* The Status control's hints. Previously dw-field__hint, which is defined only in the deal\n WORKSPACE's stylesheet under emulated encapsulation, so the rule could never match markup in\n this component and both hints rendered as unstyled body text. FIELD_STYLES is a template\n literal, so no backticks in here. */\n .mjs-field__hint { display: block; margin-top: var(--mj-space-1); color: var(--mj-text-muted); font-size: 0.78rem; }\n .mjs-reopen { display: flex; flex-direction: column; gap: var(--mj-space-2); margin-top: var(--mj-space-2); }\n .mjs-reopen__field { display: flex; flex-direction: column; gap: var(--mj-space-1); font-size: 0.82rem; }\n .mjs-reopen__field textarea { width: 100%; font: inherit; }\n .mjs-reopen__row { display: flex; gap: var(--mj-space-2); }\n .mjs-reopen__confirm {\n border: 1px solid var(--mj-brand-primary); background: var(--mj-brand-primary);\n color: var(--mj-text-on-brand); border-radius: var(--mj-radius-sm);\n padding: var(--mj-space-1) var(--mj-space-3); cursor: pointer; font: inherit;\n }\n .mjs-reopen__confirm:disabled { opacity: 0.55; cursor: not-allowed; }\n .mjs-reopen__cancel {\n border: 1px solid var(--mj-border-default); background: transparent; color: var(--mj-text-default);\n border-radius: var(--mj-radius-sm); padding: var(--mj-space-1) var(--mj-space-3); cursor: pointer; font: inherit;\n }\n .mjs-reopen__msg { font-size: 0.82rem; color: var(--mj-status-success); }\n .mjs-reopen__msg.is-error { color: var(--mj-status-warning); font-weight: 500; }\n .mjs-reopen__issue { font-size: 0.78rem; color: var(--mj-status-warning); }\n .mjs-field .mj-forms-field {\n display: flex; flex-direction: column; align-items: stretch; gap: 4px; padding: 0;\n }\n .mjs-field .mj-forms-field-label {\n font-size: var(--mj-text-xs); font-weight: 700; letter-spacing: .06em;\n text-transform: uppercase; color: var(--mj-text-muted);\n }\n .mjs-field .mj-forms-field--editing:hover { margin: 0; padding: 0; }\n /* The NATIVE selects this file draws itself, brought into line with the shared control\n (bc-aidp-next-golive#259 item 2: \"Status drop-down list does not seem to be styled consistently\n with rest of the app (shorter font)\").\n\n IT IS A NATIVE SELECT ON PURPOSE. mj-form-field renders a foreign key as an unfiltered dropdown\n off the related entity, which offered Won and Lost and bypassed the audited close -- golive#205,\n and the comment at the Status control says so. Opting out of the component meant opting out of\n its CSS too, and nothing put that back: a bare select inherits the browser's own font, about a\n point smaller than everything around it, which is exactly what was reported.\n\n So this restates .mj-forms-field-input's typography and underline rather than swapping the\n control back. The values are copied from that rule deliberately -- there is no shared token for\n \"a form control\" to reference, and inventing one here would be this app's guess at a platform\n decision.\n\n NO appearance: none. The shared control is a div that draws its own chevron; a native select\n stripped of its appearance would lose the arrow and have nothing to replace it, which is a worse\n inconsistency than the one being fixed.\n\n Scoped to this file's own classes because encapsulation is None on every panel that uses these\n styles, so an unscoped bare-element rule would reach the whole application. All three selects the\n deal form owns -- Status, and the loss reason on the pipeline and close panels -- sit inside one\n of these two. */\n .mjs-field select, .mjs-reopen__field select {\n font-size: 14px; font-family: inherit; color: var(--mj-text-primary);\n background: transparent; border: none;\n border-bottom: 1.5px solid var(--mj-border-default);\n padding: 4px 0; width: 100%; cursor: pointer; outline: none;\n transition: border-color var(--mj-transition-base) ease,\n background var(--mj-transition-base) ease;\n }\n .mjs-field select:focus, .mjs-reopen__field select:focus {\n border-bottom-color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, transparent);\n border-radius: 4px 4px 0 0; padding: 4px 6px;\n }\n /* Matches .mj-forms-field--readonly, which is how the shared control shows a field it will not\n let you change -- the Status select is disabled whenever the deal is locked. */\n .mjs-field select:disabled, .mjs-reopen__field select:disabled {\n opacity: 0.7; cursor: not-allowed;\n }\n /* A money field the panel drew itself. It carries .mj-forms-field-value too, so the size, colour\n and row height are the shared control's rather than a second opinion about them; this adds only\n what money specifically wants -- figures of equal width, so a column of amounts lines up. */\n .mjs-field__money { font-variant-numeric: tabular-nums; }\n"] }]
|
|
2646
2718
|
}], null, null); })();
|
|
2647
|
-
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MJSDealPartyPanel, { className: "MJSDealPartyPanel", filePath: "lib/form-panels/deal-form.panels.ts", lineNumber:
|
|
2719
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MJSDealPartyPanel, { className: "MJSDealPartyPanel", filePath: "lib/form-panels/deal-form.panels.ts", lineNumber: 1855 }); })();
|
|
2648
2720
|
/**
|
|
2649
2721
|
* The Commercial section's fields, at module scope for the reason `PARTY_FIELDS` is: `Object.create`
|
|
2650
2722
|
* -- how these panels are built in tests, because they inject nothing -- does NOT run property
|
|
@@ -2721,7 +2793,7 @@ export { MJSDealCommercialPanel };
|
|
|
2721
2793
|
</mj-collapsible-panel>
|
|
2722
2794
|
`, styles: ["\n .mjs-fields {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: var(--mj-space-4) var(--mj-space-5);\n padding: var(--mj-space-4) var(--mj-space-5);\n }\n @media (max-width: 720px) { .mjs-fields { grid-template-columns: 1fr; } }\n .mjs-field { min-width: 0; }\n .mjs-field--span { grid-column: 1 / -1; }\n /* The Status control's hints. Previously dw-field__hint, which is defined only in the deal\n WORKSPACE's stylesheet under emulated encapsulation, so the rule could never match markup in\n this component and both hints rendered as unstyled body text. FIELD_STYLES is a template\n literal, so no backticks in here. */\n .mjs-field__hint { display: block; margin-top: var(--mj-space-1); color: var(--mj-text-muted); font-size: 0.78rem; }\n .mjs-reopen { display: flex; flex-direction: column; gap: var(--mj-space-2); margin-top: var(--mj-space-2); }\n .mjs-reopen__field { display: flex; flex-direction: column; gap: var(--mj-space-1); font-size: 0.82rem; }\n .mjs-reopen__field textarea { width: 100%; font: inherit; }\n .mjs-reopen__row { display: flex; gap: var(--mj-space-2); }\n .mjs-reopen__confirm {\n border: 1px solid var(--mj-brand-primary); background: var(--mj-brand-primary);\n color: var(--mj-text-on-brand); border-radius: var(--mj-radius-sm);\n padding: var(--mj-space-1) var(--mj-space-3); cursor: pointer; font: inherit;\n }\n .mjs-reopen__confirm:disabled { opacity: 0.55; cursor: not-allowed; }\n .mjs-reopen__cancel {\n border: 1px solid var(--mj-border-default); background: transparent; color: var(--mj-text-default);\n border-radius: var(--mj-radius-sm); padding: var(--mj-space-1) var(--mj-space-3); cursor: pointer; font: inherit;\n }\n .mjs-reopen__msg { font-size: 0.82rem; color: var(--mj-status-success); }\n .mjs-reopen__msg.is-error { color: var(--mj-status-warning); font-weight: 500; }\n .mjs-reopen__issue { font-size: 0.78rem; color: var(--mj-status-warning); }\n .mjs-field .mj-forms-field {\n display: flex; flex-direction: column; align-items: stretch; gap: 4px; padding: 0;\n }\n .mjs-field .mj-forms-field-label {\n font-size: var(--mj-text-xs); font-weight: 700; letter-spacing: .06em;\n text-transform: uppercase; color: var(--mj-text-muted);\n }\n .mjs-field .mj-forms-field--editing:hover { margin: 0; padding: 0; }\n /* The NATIVE selects this file draws itself, brought into line with the shared control\n (bc-aidp-next-golive#259 item 2: \"Status drop-down list does not seem to be styled consistently\n with rest of the app (shorter font)\").\n\n IT IS A NATIVE SELECT ON PURPOSE. mj-form-field renders a foreign key as an unfiltered dropdown\n off the related entity, which offered Won and Lost and bypassed the audited close -- golive#205,\n and the comment at the Status control says so. Opting out of the component meant opting out of\n its CSS too, and nothing put that back: a bare select inherits the browser's own font, about a\n point smaller than everything around it, which is exactly what was reported.\n\n So this restates .mj-forms-field-input's typography and underline rather than swapping the\n control back. The values are copied from that rule deliberately -- there is no shared token for\n \"a form control\" to reference, and inventing one here would be this app's guess at a platform\n decision.\n\n NO appearance: none. The shared control is a div that draws its own chevron; a native select\n stripped of its appearance would lose the arrow and have nothing to replace it, which is a worse\n inconsistency than the one being fixed.\n\n Scoped to this file's own classes because encapsulation is None on every panel that uses these\n styles, so an unscoped bare-element rule would reach the whole application. All three selects the\n deal form owns -- Status, and the loss reason on the pipeline and close panels -- sit inside one\n of these two. */\n .mjs-field select, .mjs-reopen__field select {\n font-size: 14px; font-family: inherit; color: var(--mj-text-primary);\n background: transparent; border: none;\n border-bottom: 1.5px solid var(--mj-border-default);\n padding: 4px 0; width: 100%; cursor: pointer; outline: none;\n transition: border-color var(--mj-transition-base) ease,\n background var(--mj-transition-base) ease;\n }\n .mjs-field select:focus, .mjs-reopen__field select:focus {\n border-bottom-color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, transparent);\n border-radius: 4px 4px 0 0; padding: 4px 6px;\n }\n /* Matches .mj-forms-field--readonly, which is how the shared control shows a field it will not\n let you change -- the Status select is disabled whenever the deal is locked. */\n .mjs-field select:disabled, .mjs-reopen__field select:disabled {\n opacity: 0.7; cursor: not-allowed;\n }\n /* A money field the panel drew itself. It carries .mj-forms-field-value too, so the size, colour\n and row height are the shared control's rather than a second opinion about them; this adds only\n what money specifically wants -- figures of equal width, so a column of amounts lines up. */\n .mjs-field__money { font-variant-numeric: tabular-nums; }\n"] }]
|
|
2723
2795
|
}], null, null); })();
|
|
2724
|
-
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MJSDealCommercialPanel, { className: "MJSDealCommercialPanel", filePath: "lib/form-panels/deal-form.panels.ts", lineNumber:
|
|
2796
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MJSDealCommercialPanel, { className: "MJSDealCommercialPanel", filePath: "lib/form-panels/deal-form.panels.ts", lineNumber: 1948 }); })();
|
|
2725
2797
|
let MJSDealLinesPanel = class MJSDealLinesPanel extends BaseFormPanel {
|
|
2726
2798
|
/**
|
|
2727
2799
|
* Whether the deal's persisted status locks it.
|
|
@@ -3000,7 +3072,7 @@ export { MJSDealLinesPanel };
|
|
|
3000
3072
|
type: ViewChild,
|
|
3001
3073
|
args: [ExplorerEntityDataGridComponent]
|
|
3002
3074
|
}] }); })();
|
|
3003
|
-
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MJSDealLinesPanel, { className: "MJSDealLinesPanel", filePath: "lib/form-panels/deal-form.panels.ts", lineNumber:
|
|
3075
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MJSDealLinesPanel, { className: "MJSDealLinesPanel", filePath: "lib/form-panels/deal-form.panels.ts", lineNumber: 2068 }); })();
|
|
3004
3076
|
let MJSDealMotionPanel = class MJSDealMotionPanel extends MJSDealFieldPanel {
|
|
3005
3077
|
/**
|
|
3006
3078
|
* ── THE TWO ORDER/CONTRACT CHANGES HERE (bc-aidp-next-golive#226) ───────────────────────────
|
|
@@ -3069,7 +3141,7 @@ export { MJSDealMotionPanel };
|
|
|
3069
3141
|
</mj-collapsible-panel>
|
|
3070
3142
|
`, styles: ["\n .mjs-fields {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: var(--mj-space-4) var(--mj-space-5);\n padding: var(--mj-space-4) var(--mj-space-5);\n }\n @media (max-width: 720px) { .mjs-fields { grid-template-columns: 1fr; } }\n .mjs-field { min-width: 0; }\n .mjs-field--span { grid-column: 1 / -1; }\n /* The Status control's hints. Previously dw-field__hint, which is defined only in the deal\n WORKSPACE's stylesheet under emulated encapsulation, so the rule could never match markup in\n this component and both hints rendered as unstyled body text. FIELD_STYLES is a template\n literal, so no backticks in here. */\n .mjs-field__hint { display: block; margin-top: var(--mj-space-1); color: var(--mj-text-muted); font-size: 0.78rem; }\n .mjs-reopen { display: flex; flex-direction: column; gap: var(--mj-space-2); margin-top: var(--mj-space-2); }\n .mjs-reopen__field { display: flex; flex-direction: column; gap: var(--mj-space-1); font-size: 0.82rem; }\n .mjs-reopen__field textarea { width: 100%; font: inherit; }\n .mjs-reopen__row { display: flex; gap: var(--mj-space-2); }\n .mjs-reopen__confirm {\n border: 1px solid var(--mj-brand-primary); background: var(--mj-brand-primary);\n color: var(--mj-text-on-brand); border-radius: var(--mj-radius-sm);\n padding: var(--mj-space-1) var(--mj-space-3); cursor: pointer; font: inherit;\n }\n .mjs-reopen__confirm:disabled { opacity: 0.55; cursor: not-allowed; }\n .mjs-reopen__cancel {\n border: 1px solid var(--mj-border-default); background: transparent; color: var(--mj-text-default);\n border-radius: var(--mj-radius-sm); padding: var(--mj-space-1) var(--mj-space-3); cursor: pointer; font: inherit;\n }\n .mjs-reopen__msg { font-size: 0.82rem; color: var(--mj-status-success); }\n .mjs-reopen__msg.is-error { color: var(--mj-status-warning); font-weight: 500; }\n .mjs-reopen__issue { font-size: 0.78rem; color: var(--mj-status-warning); }\n .mjs-field .mj-forms-field {\n display: flex; flex-direction: column; align-items: stretch; gap: 4px; padding: 0;\n }\n .mjs-field .mj-forms-field-label {\n font-size: var(--mj-text-xs); font-weight: 700; letter-spacing: .06em;\n text-transform: uppercase; color: var(--mj-text-muted);\n }\n .mjs-field .mj-forms-field--editing:hover { margin: 0; padding: 0; }\n /* The NATIVE selects this file draws itself, brought into line with the shared control\n (bc-aidp-next-golive#259 item 2: \"Status drop-down list does not seem to be styled consistently\n with rest of the app (shorter font)\").\n\n IT IS A NATIVE SELECT ON PURPOSE. mj-form-field renders a foreign key as an unfiltered dropdown\n off the related entity, which offered Won and Lost and bypassed the audited close -- golive#205,\n and the comment at the Status control says so. Opting out of the component meant opting out of\n its CSS too, and nothing put that back: a bare select inherits the browser's own font, about a\n point smaller than everything around it, which is exactly what was reported.\n\n So this restates .mj-forms-field-input's typography and underline rather than swapping the\n control back. The values are copied from that rule deliberately -- there is no shared token for\n \"a form control\" to reference, and inventing one here would be this app's guess at a platform\n decision.\n\n NO appearance: none. The shared control is a div that draws its own chevron; a native select\n stripped of its appearance would lose the arrow and have nothing to replace it, which is a worse\n inconsistency than the one being fixed.\n\n Scoped to this file's own classes because encapsulation is None on every panel that uses these\n styles, so an unscoped bare-element rule would reach the whole application. All three selects the\n deal form owns -- Status, and the loss reason on the pipeline and close panels -- sit inside one\n of these two. */\n .mjs-field select, .mjs-reopen__field select {\n font-size: 14px; font-family: inherit; color: var(--mj-text-primary);\n background: transparent; border: none;\n border-bottom: 1.5px solid var(--mj-border-default);\n padding: 4px 0; width: 100%; cursor: pointer; outline: none;\n transition: border-color var(--mj-transition-base) ease,\n background var(--mj-transition-base) ease;\n }\n .mjs-field select:focus, .mjs-reopen__field select:focus {\n border-bottom-color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, transparent);\n border-radius: 4px 4px 0 0; padding: 4px 6px;\n }\n /* Matches .mj-forms-field--readonly, which is how the shared control shows a field it will not\n let you change -- the Status select is disabled whenever the deal is locked. */\n .mjs-field select:disabled, .mjs-reopen__field select:disabled {\n opacity: 0.7; cursor: not-allowed;\n }\n /* A money field the panel drew itself. It carries .mj-forms-field-value too, so the size, colour\n and row height are the shared control's rather than a second opinion about them; this adds only\n what money specifically wants -- figures of equal width, so a column of amounts lines up. */\n .mjs-field__money { font-variant-numeric: tabular-nums; }\n"] }]
|
|
3071
3143
|
}], null, null); })();
|
|
3072
|
-
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MJSDealMotionPanel, { className: "MJSDealMotionPanel", filePath: "lib/form-panels/deal-form.panels.ts", lineNumber:
|
|
3144
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MJSDealMotionPanel, { className: "MJSDealMotionPanel", filePath: "lib/form-panels/deal-form.panels.ts", lineNumber: 2254 }); })();
|
|
3073
3145
|
let MJSDealClosePanel = class MJSDealClosePanel extends MJSDealFieldPanel {
|
|
3074
3146
|
PanelOpen = false;
|
|
3075
3147
|
ReopenPanelOpen = false;
|
|
@@ -3336,10 +3408,18 @@ let MJSDealClosePanel = class MJSDealClosePanel extends MJSDealFieldPanel {
|
|
|
3336
3408
|
* The audited way back through the lock (bc-aidp-next-golive#205).
|
|
3337
3409
|
*
|
|
3338
3410
|
* Mirrors {@link ConfirmClose}, including the part that is easy to drop: a reopen can return
|
|
3339
|
-
* `Success: true` WITH issues, and those are the ones that matter most.
|
|
3340
|
-
*
|
|
3341
|
-
*
|
|
3342
|
-
*
|
|
3411
|
+
* `Success: true` WITH issues, and those are the ones that matter most. The deal reopens
|
|
3412
|
+
* regardless of what the order does, because an order-side refusal must never block a stage
|
|
3413
|
+
* change — so this list is the only thing standing between the rep and a live deal pointing at a
|
|
3414
|
+
* dead order.
|
|
3415
|
+
*
|
|
3416
|
+
* THIS USED TO SAY the reopen "asks the order to come back while it sits at `Voided`, which orders
|
|
3417
|
+
* treats as terminal". It does not: `TRANSITIONS.Voided` is `['Draft', 'Quoted']`, so
|
|
3418
|
+
* `IsTerminal('Voided')` is FALSE and `Confirmed` is the terminal status. Recorded once in
|
|
3419
|
+
* `docs/DECISIONS.md` D-OS4; KI-27 is the lifecycle collapse that caused it, not the transition
|
|
3420
|
+
* fact itself. The cases that genuinely leave an order behind are a BOOKED order, which the reopen
|
|
3421
|
+
* refuses outright, and — until golive#205 — a restored stage that declared nothing, which asked
|
|
3422
|
+
* the order for nothing and said nothing either.
|
|
3343
3423
|
*
|
|
3344
3424
|
* IT DOES SAVE FIRST, which this comment used to say it must not. The old reasoning was that "a
|
|
3345
3425
|
* locked deal has almost nothing editable, and the close lock would refuse the save anyway". Both
|
|
@@ -3591,7 +3671,7 @@ export { MJSDealClosePanel };
|
|
|
3591
3671
|
</mj-collapsible-panel>
|
|
3592
3672
|
`, styles: ["\n .mjs-fields {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: var(--mj-space-4) var(--mj-space-5);\n padding: var(--mj-space-4) var(--mj-space-5);\n }\n @media (max-width: 720px) { .mjs-fields { grid-template-columns: 1fr; } }\n .mjs-field { min-width: 0; }\n .mjs-field--span { grid-column: 1 / -1; }\n /* The Status control's hints. Previously dw-field__hint, which is defined only in the deal\n WORKSPACE's stylesheet under emulated encapsulation, so the rule could never match markup in\n this component and both hints rendered as unstyled body text. FIELD_STYLES is a template\n literal, so no backticks in here. */\n .mjs-field__hint { display: block; margin-top: var(--mj-space-1); color: var(--mj-text-muted); font-size: 0.78rem; }\n .mjs-reopen { display: flex; flex-direction: column; gap: var(--mj-space-2); margin-top: var(--mj-space-2); }\n .mjs-reopen__field { display: flex; flex-direction: column; gap: var(--mj-space-1); font-size: 0.82rem; }\n .mjs-reopen__field textarea { width: 100%; font: inherit; }\n .mjs-reopen__row { display: flex; gap: var(--mj-space-2); }\n .mjs-reopen__confirm {\n border: 1px solid var(--mj-brand-primary); background: var(--mj-brand-primary);\n color: var(--mj-text-on-brand); border-radius: var(--mj-radius-sm);\n padding: var(--mj-space-1) var(--mj-space-3); cursor: pointer; font: inherit;\n }\n .mjs-reopen__confirm:disabled { opacity: 0.55; cursor: not-allowed; }\n .mjs-reopen__cancel {\n border: 1px solid var(--mj-border-default); background: transparent; color: var(--mj-text-default);\n border-radius: var(--mj-radius-sm); padding: var(--mj-space-1) var(--mj-space-3); cursor: pointer; font: inherit;\n }\n .mjs-reopen__msg { font-size: 0.82rem; color: var(--mj-status-success); }\n .mjs-reopen__msg.is-error { color: var(--mj-status-warning); font-weight: 500; }\n .mjs-reopen__issue { font-size: 0.78rem; color: var(--mj-status-warning); }\n .mjs-field .mj-forms-field {\n display: flex; flex-direction: column; align-items: stretch; gap: 4px; padding: 0;\n }\n .mjs-field .mj-forms-field-label {\n font-size: var(--mj-text-xs); font-weight: 700; letter-spacing: .06em;\n text-transform: uppercase; color: var(--mj-text-muted);\n }\n .mjs-field .mj-forms-field--editing:hover { margin: 0; padding: 0; }\n /* The NATIVE selects this file draws itself, brought into line with the shared control\n (bc-aidp-next-golive#259 item 2: \"Status drop-down list does not seem to be styled consistently\n with rest of the app (shorter font)\").\n\n IT IS A NATIVE SELECT ON PURPOSE. mj-form-field renders a foreign key as an unfiltered dropdown\n off the related entity, which offered Won and Lost and bypassed the audited close -- golive#205,\n and the comment at the Status control says so. Opting out of the component meant opting out of\n its CSS too, and nothing put that back: a bare select inherits the browser's own font, about a\n point smaller than everything around it, which is exactly what was reported.\n\n So this restates .mj-forms-field-input's typography and underline rather than swapping the\n control back. The values are copied from that rule deliberately -- there is no shared token for\n \"a form control\" to reference, and inventing one here would be this app's guess at a platform\n decision.\n\n NO appearance: none. The shared control is a div that draws its own chevron; a native select\n stripped of its appearance would lose the arrow and have nothing to replace it, which is a worse\n inconsistency than the one being fixed.\n\n Scoped to this file's own classes because encapsulation is None on every panel that uses these\n styles, so an unscoped bare-element rule would reach the whole application. All three selects the\n deal form owns -- Status, and the loss reason on the pipeline and close panels -- sit inside one\n of these two. */\n .mjs-field select, .mjs-reopen__field select {\n font-size: 14px; font-family: inherit; color: var(--mj-text-primary);\n background: transparent; border: none;\n border-bottom: 1.5px solid var(--mj-border-default);\n padding: 4px 0; width: 100%; cursor: pointer; outline: none;\n transition: border-color var(--mj-transition-base) ease,\n background var(--mj-transition-base) ease;\n }\n .mjs-field select:focus, .mjs-reopen__field select:focus {\n border-bottom-color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, transparent);\n border-radius: 4px 4px 0 0; padding: 4px 6px;\n }\n /* Matches .mj-forms-field--readonly, which is how the shared control shows a field it will not\n let you change -- the Status select is disabled whenever the deal is locked. */\n .mjs-field select:disabled, .mjs-reopen__field select:disabled {\n opacity: 0.7; cursor: not-allowed;\n }\n /* A money field the panel drew itself. It carries .mj-forms-field-value too, so the size, colour\n and row height are the shared control's rather than a second opinion about them; this adds only\n what money specifically wants -- figures of equal width, so a column of amounts lines up. */\n .mjs-field__money { font-variant-numeric: tabular-nums; }\n", "\n .mjs-close-action {\n padding: var(--mj-space-4) var(--mj-space-5);\n border-bottom: 1px solid var(--mj-border-default);\n display: flex; flex-direction: column; gap: var(--mj-space-3);\n }\n .mjs-close-action__start {\n align-self: flex-start; cursor: pointer;\n padding: 6px 14px; border-radius: var(--mj-radius-sm);\n border: 1px solid var(--mj-border-default); background: var(--mj-bg-surface-card);\n font-weight: 600;\n }\n .mjs-close-action__start:hover { background: var(--mj-bg-surface-hover); }\n .mjs-close-action__hint { color: var(--mj-text-muted); font-size: 0.78rem; }\n .mjs-close-action__form { display: flex; flex-direction: column; gap: var(--mj-space-3); max-width: 520px; }\n .mjs-close-action__row { display: flex; gap: var(--mj-space-4); align-items: center; }\n .mjs-close-action__field { display: flex; flex-direction: column; gap: 4px; }\n .mjs-close-action__field > span { font-size: 0.78rem; color: var(--mj-text-muted); }\n .mjs-close-action__confirm {\n cursor: pointer; padding: 6px 14px; border-radius: var(--mj-radius-sm);\n border: 1px solid var(--mj-brand-primary); background: var(--mj-brand-primary); color: var(--mj-text-on-brand);\n font-weight: 600;\n }\n .mjs-close-action__confirm:disabled { opacity: 0.5; cursor: not-allowed; }\n .mjs-close-action__cancel {\n cursor: pointer; padding: 6px 14px; border-radius: var(--mj-radius-sm);\n border: 1px solid var(--mj-border-default); background: transparent;\n }\n .mjs-close-action__msg { font-size: 0.82rem; color: var(--mj-status-success); }\n .mjs-close-action__msg.is-error { color: var(--mj-status-warning); font-weight: 500; }\n .mjs-close-action__issue { font-size: 0.78rem; color: var(--mj-status-warning); }\n"] }]
|
|
3593
3673
|
}], null, null); })();
|
|
3594
|
-
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MJSDealClosePanel, { className: "MJSDealClosePanel", filePath: "lib/form-panels/deal-form.panels.ts", lineNumber:
|
|
3674
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MJSDealClosePanel, { className: "MJSDealClosePanel", filePath: "lib/form-panels/deal-form.panels.ts", lineNumber: 2440 }); })();
|
|
3595
3675
|
/* ── Related, renamed ─────────────────────────────────────────────────────── */
|
|
3596
3676
|
let MJSDealTeamGridPanel = class MJSDealTeamGridPanel extends BaseFormPanel {
|
|
3597
3677
|
Entity = MJS_ENTITIES.DealTeamMember;
|
|
@@ -3641,7 +3721,7 @@ export { MJSDealTeamGridPanel };
|
|
|
3641
3721
|
</mj-collapsible-panel>
|
|
3642
3722
|
`, styles: [".mjs-deal-empty { margin: 0; padding: var(--mj-space-4) var(--mj-space-5); color: var(--mj-text-muted); }"] }]
|
|
3643
3723
|
}], null, null); })();
|
|
3644
|
-
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MJSDealTeamGridPanel, { className: "MJSDealTeamGridPanel", filePath: "lib/form-panels/deal-form.panels.ts", lineNumber:
|
|
3724
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MJSDealTeamGridPanel, { className: "MJSDealTeamGridPanel", filePath: "lib/form-panels/deal-form.panels.ts", lineNumber: 2851 }); })();
|
|
3645
3725
|
let MJSDealBuyingTeamPanel = class MJSDealBuyingTeamPanel extends BaseFormPanel {
|
|
3646
3726
|
Entity = MJS_ENTITIES.DealContactRole;
|
|
3647
3727
|
OnDataLoad(event) {
|
|
@@ -3690,7 +3770,7 @@ export { MJSDealBuyingTeamPanel };
|
|
|
3690
3770
|
</mj-collapsible-panel>
|
|
3691
3771
|
`, styles: [".mjs-deal-empty { margin: 0; padding: var(--mj-space-4) var(--mj-space-5); color: var(--mj-text-muted); }"] }]
|
|
3692
3772
|
}], null, null); })();
|
|
3693
|
-
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MJSDealBuyingTeamPanel, { className: "MJSDealBuyingTeamPanel", filePath: "lib/form-panels/deal-form.panels.ts", lineNumber:
|
|
3773
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MJSDealBuyingTeamPanel, { className: "MJSDealBuyingTeamPanel", filePath: "lib/form-panels/deal-form.panels.ts", lineNumber: 2890 }); })();
|
|
3694
3774
|
let MJSDealActivityPanel = class MJSDealActivityPanel extends BaseFormPanel {
|
|
3695
3775
|
cdr = inject(ChangeDetectorRef);
|
|
3696
3776
|
ActivityEntity = null;
|
|
@@ -3791,7 +3871,7 @@ export { MJSDealActivityPanel };
|
|
|
3791
3871
|
</mj-collapsible-panel>
|
|
3792
3872
|
`, styles: [".mjs-deal-empty { margin: 0; padding: var(--mj-space-4) var(--mj-space-5); color: var(--mj-text-muted); }", "\n .mjs-deal-activity { display: flex; flex-direction: column; gap: var(--mj-space-3); padding: var(--mj-space-3) var(--mj-space-4) var(--mj-space-5); min-height: 0; }\n .mjs-deal-activity__viewer {\n min-height: 420px; height: 480px;\n display: flex; flex-direction: column;\n border: 1px solid var(--mj-border-default); border-radius: var(--mj-radius-md); overflow: hidden;\n }\n .mjs-deal-activity__viewer mj-entity-viewer {\n display: flex; flex-direction: column; flex: 1 1 auto; height: 100%; width: 100%;\n }\n "] }]
|
|
3793
3873
|
}], null, null); })();
|
|
3794
|
-
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MJSDealActivityPanel, { className: "MJSDealActivityPanel", filePath: "lib/form-panels/deal-form.panels.ts", lineNumber:
|
|
3874
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MJSDealActivityPanel, { className: "MJSDealActivityPanel", filePath: "lib/form-panels/deal-form.panels.ts", lineNumber: 2944 }); })();
|
|
3795
3875
|
let MJSDealHistoryPanel = class MJSDealHistoryPanel extends BaseFormPanel {
|
|
3796
3876
|
Entity = MJS_ENTITIES.DealStageEvent;
|
|
3797
3877
|
OnDataLoad(event) {
|
|
@@ -3842,7 +3922,7 @@ export { MJSDealHistoryPanel };
|
|
|
3842
3922
|
</mj-collapsible-panel>
|
|
3843
3923
|
`, styles: [".mjs-deal-empty { margin: 0; padding: var(--mj-space-4) var(--mj-space-5); color: var(--mj-text-muted); }"] }]
|
|
3844
3924
|
}], null, null); })();
|
|
3845
|
-
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MJSDealHistoryPanel, { className: "MJSDealHistoryPanel", filePath: "lib/form-panels/deal-form.panels.ts", lineNumber:
|
|
3925
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MJSDealHistoryPanel, { className: "MJSDealHistoryPanel", filePath: "lib/form-panels/deal-form.panels.ts", lineNumber: 3047 }); })();
|
|
3846
3926
|
let MJSDealSchedulePanel = class MJSDealSchedulePanel extends BaseFormPanel {
|
|
3847
3927
|
Entity = MJS_ENTITIES.DealPaymentSchedule;
|
|
3848
3928
|
OnDataLoad(event) {
|
|
@@ -3891,5 +3971,5 @@ export { MJSDealSchedulePanel };
|
|
|
3891
3971
|
</mj-collapsible-panel>
|
|
3892
3972
|
`, styles: [".mjs-deal-empty { margin: 0; padding: var(--mj-space-4) var(--mj-space-5); color: var(--mj-text-muted); }"] }]
|
|
3893
3973
|
}], null, null); })();
|
|
3894
|
-
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MJSDealSchedulePanel, { className: "MJSDealSchedulePanel", filePath: "lib/form-panels/deal-form.panels.ts", lineNumber:
|
|
3974
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MJSDealSchedulePanel, { className: "MJSDealSchedulePanel", filePath: "lib/form-panels/deal-form.panels.ts", lineNumber: 3086 }); })();
|
|
3895
3975
|
//# sourceMappingURL=deal-form.panels.js.map
|