@mj-biz-apps/contracts-ng 0.2.0 → 0.4.0
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/contract-form.panels.d.ts +111 -0
- package/dist/lib/form-panels/contract-form.panels.d.ts.map +1 -0
- package/dist/lib/form-panels/contract-form.panels.js +1002 -0
- package/dist/lib/form-panels/contract-form.panels.js.map +1 -0
- package/dist/lib/form-panels/contract-form.policy.d.ts +5 -0
- package/dist/lib/form-panels/contract-form.policy.d.ts.map +1 -0
- package/dist/lib/form-panels/contract-form.policy.js +33 -0
- package/dist/lib/form-panels/contract-form.policy.js.map +1 -0
- package/dist/lib/form-panels/contract.panels.d.ts +55 -3
- package/dist/lib/form-panels/contract.panels.d.ts.map +1 -1
- package/dist/lib/form-panels/contract.panels.js +619 -362
- package/dist/lib/form-panels/contract.panels.js.map +1 -1
- package/dist/lib/form-panels/organization.panels.d.ts +4 -13
- package/dist/lib/form-panels/organization.panels.d.ts.map +1 -1
- package/dist/lib/form-panels/organization.panels.js +54 -62
- package/dist/lib/form-panels/organization.panels.js.map +1 -1
- package/dist/lib/form-panels/person.panels.d.ts +14 -0
- package/dist/lib/form-panels/person.panels.d.ts.map +1 -0
- package/dist/lib/form-panels/person.panels.js +108 -0
- package/dist/lib/form-panels/person.panels.js.map +1 -0
- package/dist/lib/form-panels/supersede.panel.d.ts +29 -3
- package/dist/lib/form-panels/supersede.panel.d.ts.map +1 -1
- package/dist/lib/form-panels/supersede.panel.js +81 -23
- package/dist/lib/form-panels/supersede.panel.js.map +1 -1
- package/dist/lib/pages/contracts-dashboard.page.d.ts +37 -17
- package/dist/lib/pages/contracts-dashboard.page.d.ts.map +1 -1
- package/dist/lib/pages/contracts-dashboard.page.js +365 -63
- package/dist/lib/pages/contracts-dashboard.page.js.map +1 -1
- package/dist/lib/sections/section-shell.component.js +2 -2
- package/dist/public-api.d.ts +3 -1
- package/dist/public-api.d.ts.map +1 -1
- package/dist/public-api.js +15 -4
- package/dist/public-api.js.map +1 -1
- package/package.json +2 -3
- package/dist/lib/form-panels/record-files.panel.d.ts +0 -151
- package/dist/lib/form-panels/record-files.panel.d.ts.map +0 -1
- package/dist/lib/form-panels/record-files.panel.js +0 -1046
- package/dist/lib/form-panels/record-files.panel.js.map +0 -1
|
@@ -14,7 +14,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
14
14
|
*
|
|
15
15
|
* 1. **The panels were not `<mj-collapsible-panel>`s.** They were hand-rolled `<div class="card">`s, so
|
|
16
16
|
* they had none of MJ's panel chrome — hence text with no card behind it, cards touching each other,
|
|
17
|
-
* and content overflowing. The
|
|
17
|
+
* and content overflowing. The panels that looked right were the ones built on
|
|
18
18
|
* the real component.
|
|
19
19
|
* 2a. **`contributionKey` MUST EQUAL the panel's own `SectionKey`, and must DIFFER from
|
|
20
20
|
* `replacesSectionKey`.** This is the rule that took longest to find, because breaking it fails
|
|
@@ -42,84 +42,219 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
42
42
|
import { ChangeDetectorRef, Component, ViewEncapsulation, inject } from '@angular/core';
|
|
43
43
|
import { CommonModule } from '@angular/common';
|
|
44
44
|
import { FormsModule } from '@angular/forms';
|
|
45
|
+
import { CompositeKey } from '@memberjunction/core';
|
|
46
|
+
import { UserInfoEngine } from '@memberjunction/core-entities';
|
|
45
47
|
import { RegisterClassEx } from '@memberjunction/global';
|
|
46
48
|
import { BaseFormPanel, BaseFormsModule } from '@memberjunction/ng-base-forms';
|
|
47
49
|
import { HierarchyTreeComponent } from '@memberjunction/ng-hierarchy-tree';
|
|
48
|
-
import {
|
|
49
|
-
import { MJC_ENTITIES } from '../data/entity-names';
|
|
50
|
+
import { MJC_ENTITIES, MJC_FOREIGN_ENTITIES } from '../data/entity-names';
|
|
50
51
|
import * as i0 from "@angular/core";
|
|
51
|
-
import * as i1 from "@
|
|
52
|
-
import * as i2 from "@angular/
|
|
53
|
-
import * as i3 from "@
|
|
54
|
-
function
|
|
55
|
-
i0.ɵɵ
|
|
52
|
+
import * as i1 from "@memberjunction/ng-base-forms";
|
|
53
|
+
import * as i2 from "@angular/common";
|
|
54
|
+
import * as i3 from "@angular/forms";
|
|
55
|
+
function MJCContractHeroPanel_Conditional_4_Template(rf, ctx) { if (rf & 1) {
|
|
56
|
+
i0.ɵɵelement(0, "span", 4);
|
|
57
|
+
} if (rf & 2) {
|
|
58
|
+
const ctx_r0 = i0.ɵɵnextContext();
|
|
59
|
+
i0.ɵɵproperty("title", ctx_r0.State);
|
|
60
|
+
i0.ɵɵattribute("data-tone", ctx_r0.StatusTone);
|
|
61
|
+
} }
|
|
62
|
+
function MJCContractHeroPanel_Conditional_9_Template(rf, ctx) { if (rf & 1) {
|
|
63
|
+
i0.ɵɵelementStart(0, "div", 8);
|
|
56
64
|
i0.ɵɵtext(1);
|
|
57
|
-
i0.ɵɵ
|
|
65
|
+
i0.ɵɵelementEnd();
|
|
66
|
+
} if (rf & 2) {
|
|
67
|
+
const ctx_r0 = i0.ɵɵnextContext();
|
|
68
|
+
i0.ɵɵadvance();
|
|
69
|
+
i0.ɵɵtextInterpolate(ctx_r0.Record.ContractNumber);
|
|
70
|
+
} }
|
|
71
|
+
function MJCContractHeroPanel_Conditional_16_Template(rf, ctx) { if (rf & 1) {
|
|
72
|
+
i0.ɵɵelementStart(0, "span", 12);
|
|
73
|
+
i0.ɵɵtext(1);
|
|
74
|
+
i0.ɵɵelementEnd();
|
|
58
75
|
} if (rf & 2) {
|
|
59
76
|
const ctx_r0 = i0.ɵɵnextContext();
|
|
60
77
|
i0.ɵɵadvance();
|
|
61
78
|
i0.ɵɵtextInterpolate(ctx_r0.TypeName);
|
|
62
79
|
} }
|
|
63
|
-
function
|
|
64
|
-
i0.ɵɵ
|
|
65
|
-
i0.ɵɵ
|
|
80
|
+
function MJCContractHeroPanel_Conditional_17_Template(rf, ctx) { if (rf & 1) {
|
|
81
|
+
i0.ɵɵelementStart(0, "span", 13);
|
|
82
|
+
i0.ɵɵelement(1, "i", 16);
|
|
66
83
|
i0.ɵɵtext(2, " Agreement modified ");
|
|
67
|
-
i0.ɵɵ
|
|
84
|
+
i0.ɵɵelementEnd();
|
|
68
85
|
} }
|
|
69
|
-
function
|
|
70
|
-
i0.ɵɵ
|
|
71
|
-
i0.ɵɵ
|
|
86
|
+
function MJCContractHeroPanel_Conditional_18_Template(rf, ctx) { if (rf & 1) {
|
|
87
|
+
i0.ɵɵelementStart(0, "span", 14);
|
|
88
|
+
i0.ɵɵelement(1, "i", 17);
|
|
72
89
|
i0.ɵɵtext(2, " Awaiting document ");
|
|
73
|
-
i0.ɵɵ
|
|
90
|
+
i0.ɵɵelementEnd();
|
|
74
91
|
} }
|
|
75
|
-
function
|
|
76
|
-
i0.ɵɵ
|
|
77
|
-
i0.ɵɵ
|
|
78
|
-
i0.ɵɵ
|
|
79
|
-
i0.ɵɵtext(
|
|
80
|
-
i0.ɵɵ
|
|
92
|
+
function MJCContractHeroPanel_Conditional_21_Conditional_9_Template(rf, ctx) { if (rf & 1) {
|
|
93
|
+
const _r2 = i0.ɵɵgetCurrentView();
|
|
94
|
+
i0.ɵɵelementStart(0, "button", 26);
|
|
95
|
+
i0.ɵɵlistener("click", function MJCContractHeroPanel_Conditional_21_Conditional_9_Template_button_click_0_listener($event) { i0.ɵɵrestoreView(_r2); const ctx_r0 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r0.OpenCustomer($event)); });
|
|
96
|
+
i0.ɵɵtext(1);
|
|
97
|
+
i0.ɵɵelementEnd();
|
|
81
98
|
} if (rf & 2) {
|
|
82
|
-
const ctx_r0 = i0.ɵɵnextContext();
|
|
83
|
-
i0.ɵɵadvance(
|
|
84
|
-
i0.ɵɵtextInterpolate(ctx_r0.
|
|
99
|
+
const ctx_r0 = i0.ɵɵnextContext(2);
|
|
100
|
+
i0.ɵɵadvance();
|
|
101
|
+
i0.ɵɵtextInterpolate(ctx_r0.CustomerName);
|
|
85
102
|
} }
|
|
86
|
-
function
|
|
87
|
-
i0.ɵɵ
|
|
88
|
-
i0.ɵɵtext(1
|
|
89
|
-
i0.ɵɵ
|
|
103
|
+
function MJCContractHeroPanel_Conditional_21_Conditional_10_Template(rf, ctx) { if (rf & 1) {
|
|
104
|
+
i0.ɵɵelementStart(0, "span", 21);
|
|
105
|
+
i0.ɵɵtext(1);
|
|
106
|
+
i0.ɵɵelementEnd();
|
|
107
|
+
} if (rf & 2) {
|
|
108
|
+
const ctx_r0 = i0.ɵɵnextContext(2);
|
|
109
|
+
i0.ɵɵadvance();
|
|
110
|
+
i0.ɵɵtextInterpolate(ctx_r0.CustomerName || "\u2014");
|
|
90
111
|
} }
|
|
91
|
-
function
|
|
92
|
-
i0.ɵɵ
|
|
112
|
+
function MJCContractHeroPanel_Conditional_21_Conditional_14_Template(rf, ctx) { if (rf & 1) {
|
|
113
|
+
const _r3 = i0.ɵɵgetCurrentView();
|
|
114
|
+
i0.ɵɵelementStart(0, "button", 26);
|
|
115
|
+
i0.ɵɵlistener("click", function MJCContractHeroPanel_Conditional_21_Conditional_14_Template_button_click_0_listener($event) { i0.ɵɵrestoreView(_r3); const ctx_r0 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r0.OpenContact($event)); });
|
|
93
116
|
i0.ɵɵtext(1);
|
|
94
|
-
i0.ɵɵ
|
|
117
|
+
i0.ɵɵelementEnd();
|
|
95
118
|
} if (rf & 2) {
|
|
96
|
-
const ctx_r0 = i0.ɵɵnextContext();
|
|
119
|
+
const ctx_r0 = i0.ɵɵnextContext(2);
|
|
120
|
+
i0.ɵɵadvance();
|
|
121
|
+
i0.ɵɵtextInterpolate(ctx_r0.ContactName);
|
|
122
|
+
} }
|
|
123
|
+
function MJCContractHeroPanel_Conditional_21_Conditional_15_Template(rf, ctx) { if (rf & 1) {
|
|
124
|
+
i0.ɵɵelementStart(0, "span", 21);
|
|
125
|
+
i0.ɵɵtext(1);
|
|
126
|
+
i0.ɵɵelementEnd();
|
|
127
|
+
} if (rf & 2) {
|
|
128
|
+
const ctx_r0 = i0.ɵɵnextContext(2);
|
|
129
|
+
i0.ɵɵadvance();
|
|
130
|
+
i0.ɵɵtextInterpolate(ctx_r0.ContactName || "\u2014");
|
|
131
|
+
} }
|
|
132
|
+
function MJCContractHeroPanel_Conditional_21_Conditional_39_Template(rf, ctx) { if (rf & 1) {
|
|
133
|
+
const _r4 = i0.ɵɵgetCurrentView();
|
|
134
|
+
i0.ɵɵelementStart(0, "div", 19)(1, "span", 20);
|
|
135
|
+
i0.ɵɵtext(2);
|
|
136
|
+
i0.ɵɵelementEnd();
|
|
137
|
+
i0.ɵɵelementStart(3, "button", 26);
|
|
138
|
+
i0.ɵɵlistener("click", function MJCContractHeroPanel_Conditional_21_Conditional_39_Template_button_click_3_listener($event) { i0.ɵɵrestoreView(_r4); const ctx_r0 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r0.OpenSource($event)); });
|
|
139
|
+
i0.ɵɵtext(4);
|
|
140
|
+
i0.ɵɵelementEnd()();
|
|
141
|
+
} if (rf & 2) {
|
|
142
|
+
const ctx_r0 = i0.ɵɵnextContext(2);
|
|
143
|
+
i0.ɵɵadvance(2);
|
|
144
|
+
i0.ɵɵtextInterpolate(ctx_r0.SourceLabel);
|
|
145
|
+
i0.ɵɵadvance();
|
|
146
|
+
i0.ɵɵattribute("aria-label", "Open " + (ctx_r0.SourceName || "the source record"));
|
|
97
147
|
i0.ɵɵadvance();
|
|
148
|
+
i0.ɵɵtextInterpolate1(" ", ctx_r0.SourceName || "Open", " ");
|
|
149
|
+
} }
|
|
150
|
+
function MJCContractHeroPanel_Conditional_21_Conditional_40_Template(rf, ctx) { if (rf & 1) {
|
|
151
|
+
i0.ɵɵelementStart(0, "div", 23)(1, "span", 20);
|
|
152
|
+
i0.ɵɵtext(2, "Term");
|
|
153
|
+
i0.ɵɵelementEnd();
|
|
154
|
+
i0.ɵɵelementStart(3, "span", 27);
|
|
155
|
+
i0.ɵɵtext(4);
|
|
156
|
+
i0.ɵɵelementEnd()();
|
|
157
|
+
} if (rf & 2) {
|
|
158
|
+
const ctx_r0 = i0.ɵɵnextContext(2);
|
|
159
|
+
i0.ɵɵadvance(4);
|
|
98
160
|
i0.ɵɵtextInterpolate(ctx_r0.EndsInText);
|
|
99
161
|
} }
|
|
100
|
-
function
|
|
101
|
-
i0.ɵɵ
|
|
102
|
-
i0.ɵɵ
|
|
103
|
-
i0.ɵɵ
|
|
162
|
+
function MJCContractHeroPanel_Conditional_21_Conditional_41_Template(rf, ctx) { if (rf & 1) {
|
|
163
|
+
i0.ɵɵelementStart(0, "div", 24)(1, "div", 28);
|
|
164
|
+
i0.ɵɵelement(2, "mj-form-field", 29);
|
|
165
|
+
i0.ɵɵelementEnd()();
|
|
166
|
+
} if (rf & 2) {
|
|
167
|
+
const ctx_r0 = i0.ɵɵnextContext(2);
|
|
168
|
+
i0.ɵɵadvance(2);
|
|
169
|
+
i0.ɵɵproperty("Record", ctx_r0.Record)("ShowLabel", true)("EditMode", ctx_r0.EditMode)("FormContext", ctx_r0.FormContext);
|
|
104
170
|
} }
|
|
105
|
-
function
|
|
106
|
-
i0.ɵɵ
|
|
107
|
-
i0.ɵɵtext(1, "
|
|
108
|
-
i0.ɵɵ
|
|
171
|
+
function MJCContractHeroPanel_Conditional_21_Conditional_42_Template(rf, ctx) { if (rf & 1) {
|
|
172
|
+
i0.ɵɵelementStart(0, "div", 25);
|
|
173
|
+
i0.ɵɵtext(1, "Contract number is assigned on save.");
|
|
174
|
+
i0.ɵɵelementEnd();
|
|
109
175
|
} }
|
|
110
|
-
function
|
|
111
|
-
i0.ɵɵ
|
|
112
|
-
i0.ɵɵtext(
|
|
113
|
-
i0.ɵɵ
|
|
176
|
+
function MJCContractHeroPanel_Conditional_21_Template(rf, ctx) { if (rf & 1) {
|
|
177
|
+
i0.ɵɵelementStart(0, "div", 18)(1, "div", 19)(2, "span", 20);
|
|
178
|
+
i0.ɵɵtext(3, "Company");
|
|
179
|
+
i0.ɵɵelementEnd();
|
|
180
|
+
i0.ɵɵelementStart(4, "span", 21);
|
|
181
|
+
i0.ɵɵtext(5);
|
|
182
|
+
i0.ɵɵelementEnd()();
|
|
183
|
+
i0.ɵɵelementStart(6, "div", 19)(7, "span", 20);
|
|
184
|
+
i0.ɵɵtext(8, "Customer");
|
|
185
|
+
i0.ɵɵelementEnd();
|
|
186
|
+
i0.ɵɵconditionalCreate(9, MJCContractHeroPanel_Conditional_21_Conditional_9_Template, 2, 1, "button", 22)(10, MJCContractHeroPanel_Conditional_21_Conditional_10_Template, 2, 1, "span", 21);
|
|
187
|
+
i0.ɵɵelementEnd();
|
|
188
|
+
i0.ɵɵelementStart(11, "div", 19)(12, "span", 20);
|
|
189
|
+
i0.ɵɵtext(13, "Contact");
|
|
190
|
+
i0.ɵɵelementEnd();
|
|
191
|
+
i0.ɵɵconditionalCreate(14, MJCContractHeroPanel_Conditional_21_Conditional_14_Template, 2, 1, "button", 22)(15, MJCContractHeroPanel_Conditional_21_Conditional_15_Template, 2, 1, "span", 21);
|
|
192
|
+
i0.ɵɵelementEnd();
|
|
193
|
+
i0.ɵɵelementStart(16, "div", 19)(17, "span", 20);
|
|
194
|
+
i0.ɵɵtext(18, "Executed");
|
|
195
|
+
i0.ɵɵelementEnd();
|
|
196
|
+
i0.ɵɵelementStart(19, "span", 21);
|
|
197
|
+
i0.ɵɵtext(20);
|
|
198
|
+
i0.ɵɵpipe(21, "date");
|
|
199
|
+
i0.ɵɵelementEnd()();
|
|
200
|
+
i0.ɵɵelementStart(22, "div", 19)(23, "span", 20);
|
|
201
|
+
i0.ɵɵtext(24, "Effective");
|
|
202
|
+
i0.ɵɵelementEnd();
|
|
203
|
+
i0.ɵɵelementStart(25, "span", 21);
|
|
204
|
+
i0.ɵɵtext(26);
|
|
205
|
+
i0.ɵɵpipe(27, "date");
|
|
206
|
+
i0.ɵɵelementEnd()();
|
|
207
|
+
i0.ɵɵelementStart(28, "div", 19)(29, "span", 20);
|
|
208
|
+
i0.ɵɵtext(30, "Term ends");
|
|
209
|
+
i0.ɵɵelementEnd();
|
|
210
|
+
i0.ɵɵelementStart(31, "span", 21);
|
|
211
|
+
i0.ɵɵtext(32);
|
|
212
|
+
i0.ɵɵpipe(33, "date");
|
|
213
|
+
i0.ɵɵelementEnd()();
|
|
214
|
+
i0.ɵɵelementStart(34, "div", 19)(35, "span", 20);
|
|
215
|
+
i0.ɵɵtext(36, "Agreement");
|
|
216
|
+
i0.ɵɵelementEnd();
|
|
217
|
+
i0.ɵɵelementStart(37, "span", 21);
|
|
218
|
+
i0.ɵɵtext(38);
|
|
219
|
+
i0.ɵɵelementEnd()();
|
|
220
|
+
i0.ɵɵconditionalCreate(39, MJCContractHeroPanel_Conditional_21_Conditional_39_Template, 5, 3, "div", 19);
|
|
221
|
+
i0.ɵɵelementEnd();
|
|
222
|
+
i0.ɵɵconditionalCreate(40, MJCContractHeroPanel_Conditional_21_Conditional_40_Template, 5, 1, "div", 23);
|
|
223
|
+
i0.ɵɵconditionalCreate(41, MJCContractHeroPanel_Conditional_21_Conditional_41_Template, 3, 4, "div", 24);
|
|
224
|
+
i0.ɵɵconditionalCreate(42, MJCContractHeroPanel_Conditional_21_Conditional_42_Template, 2, 0, "div", 25);
|
|
225
|
+
} if (rf & 2) {
|
|
226
|
+
const ctx_r0 = i0.ɵɵnextContext();
|
|
227
|
+
i0.ɵɵadvance(5);
|
|
228
|
+
i0.ɵɵtextInterpolate(ctx_r0.CompanyName || "\u2014");
|
|
229
|
+
i0.ɵɵadvance(4);
|
|
230
|
+
i0.ɵɵconditional(ctx_r0.Record.CustomerOrganizationID && ctx_r0.CustomerName ? 9 : 10);
|
|
231
|
+
i0.ɵɵadvance(5);
|
|
232
|
+
i0.ɵɵconditional(ctx_r0.Record.PrimaryContactPersonID && ctx_r0.ContactName ? 14 : 15);
|
|
233
|
+
i0.ɵɵadvance(6);
|
|
234
|
+
i0.ɵɵtextInterpolate(i0.ɵɵpipeBind2(21, 11, ctx_r0.Record.ExecutedDate, "d MMM y") || "\u2014");
|
|
235
|
+
i0.ɵɵadvance(6);
|
|
236
|
+
i0.ɵɵtextInterpolate(i0.ɵɵpipeBind2(27, 14, ctx_r0.Record.EffectiveDate, "d MMM y") || "\u2014");
|
|
237
|
+
i0.ɵɵadvance(6);
|
|
238
|
+
i0.ɵɵtextInterpolate(i0.ɵɵpipeBind2(33, 17, ctx_r0.Record.EndDate, "d MMM y") || "\u2014");
|
|
239
|
+
i0.ɵɵadvance(6);
|
|
240
|
+
i0.ɵɵtextInterpolate(ctx_r0.TemplateName || "\u2014");
|
|
241
|
+
i0.ɵɵadvance();
|
|
242
|
+
i0.ɵɵconditional(ctx_r0.HasSource ? 39 : -1);
|
|
243
|
+
i0.ɵɵadvance();
|
|
244
|
+
i0.ɵɵconditional(ctx_r0.DaysToEnd !== null ? 40 : -1);
|
|
245
|
+
i0.ɵɵadvance();
|
|
246
|
+
i0.ɵɵconditional(ctx_r0.EditMode ? 41 : -1);
|
|
247
|
+
i0.ɵɵadvance();
|
|
248
|
+
i0.ɵɵconditional(!ctx_r0.Record.ContractNumber ? 42 : -1);
|
|
114
249
|
} }
|
|
115
250
|
function MJCContractRenewalPanel_Conditional_8_Template(rf, ctx) { if (rf & 1) {
|
|
116
251
|
const _r1 = i0.ɵɵgetCurrentView();
|
|
117
|
-
i0.ɵɵelementStart(0, "select",
|
|
252
|
+
i0.ɵɵelementStart(0, "select", 12);
|
|
118
253
|
i0.ɵɵlistener("ngModelChange", function MJCContractRenewalPanel_Conditional_8_Template_select_ngModelChange_0_listener($event) { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.Set("AutoRenew", $event)); });
|
|
119
|
-
i0.ɵɵelementStart(1, "option",
|
|
254
|
+
i0.ɵɵelementStart(1, "option", 13);
|
|
120
255
|
i0.ɵɵtext(2, "Yes");
|
|
121
256
|
i0.ɵɵelementEnd();
|
|
122
|
-
i0.ɵɵelementStart(3, "option",
|
|
257
|
+
i0.ɵɵelementStart(3, "option", 13);
|
|
123
258
|
i0.ɵɵtext(4, "No");
|
|
124
259
|
i0.ɵɵelementEnd()();
|
|
125
260
|
} if (rf & 2) {
|
|
@@ -139,31 +274,26 @@ function MJCContractRenewalPanel_Conditional_9_Template(rf, ctx) { if (rf & 1) {
|
|
|
139
274
|
i0.ɵɵadvance();
|
|
140
275
|
i0.ɵɵtextInterpolate(ctx_r1.Record.AutoRenew ? "Yes" : "No");
|
|
141
276
|
} }
|
|
142
|
-
function
|
|
143
|
-
i0.ɵɵelementStart(0, "div", 7);
|
|
144
|
-
i0.ɵɵtext(1, "someone must act for this to continue");
|
|
145
|
-
i0.ɵɵelementEnd();
|
|
146
|
-
} }
|
|
147
|
-
function MJCContractRenewalPanel_Conditional_14_Template(rf, ctx) { if (rf & 1) {
|
|
277
|
+
function MJCContractRenewalPanel_Conditional_13_Template(rf, ctx) { if (rf & 1) {
|
|
148
278
|
const _r3 = i0.ɵɵgetCurrentView();
|
|
149
|
-
i0.ɵɵelementStart(0, "input",
|
|
150
|
-
i0.ɵɵlistener("ngModelChange", function
|
|
279
|
+
i0.ɵɵelementStart(0, "input", 14);
|
|
280
|
+
i0.ɵɵlistener("ngModelChange", function MJCContractRenewalPanel_Conditional_13_Template_input_ngModelChange_0_listener($event) { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.Set("RenewalNoticeDays", $event)); });
|
|
151
281
|
i0.ɵɵelementEnd();
|
|
152
282
|
} if (rf & 2) {
|
|
153
283
|
const ctx_r1 = i0.ɵɵnextContext();
|
|
154
284
|
i0.ɵɵproperty("ngModel", ctx_r1.Record.RenewalNoticeDays);
|
|
155
285
|
} }
|
|
156
|
-
function
|
|
286
|
+
function MJCContractRenewalPanel_Conditional_14_Template(rf, ctx) { if (rf & 1) {
|
|
157
287
|
i0.ɵɵelementStart(0, "div", 6);
|
|
158
288
|
i0.ɵɵtext(1);
|
|
159
289
|
i0.ɵɵelementEnd();
|
|
160
290
|
} if (rf & 2) {
|
|
161
291
|
const ctx_r1 = i0.ɵɵnextContext();
|
|
162
292
|
i0.ɵɵadvance();
|
|
163
|
-
i0.ɵɵtextInterpolate(ctx_r1.
|
|
293
|
+
i0.ɵɵtextInterpolate(ctx_r1.Days(ctx_r1.Record.RenewalNoticeDays));
|
|
164
294
|
} }
|
|
165
|
-
function
|
|
166
|
-
i0.ɵɵelementStart(0, "div",
|
|
295
|
+
function MJCContractRenewalPanel_Conditional_17_Template(rf, ctx) { if (rf & 1) {
|
|
296
|
+
i0.ɵɵelementStart(0, "div", 8);
|
|
167
297
|
i0.ɵɵtext(1);
|
|
168
298
|
i0.ɵɵpipe(2, "date");
|
|
169
299
|
i0.ɵɵelementEnd();
|
|
@@ -172,55 +302,55 @@ function MJCContractRenewalPanel_Conditional_16_Template(rf, ctx) { if (rf & 1)
|
|
|
172
302
|
i0.ɵɵadvance();
|
|
173
303
|
i0.ɵɵtextInterpolate1("deadline: ", i0.ɵɵpipeBind2(2, 1, ctx_r1.NoticeDeadline, "d MMM y"));
|
|
174
304
|
} }
|
|
175
|
-
function
|
|
305
|
+
function MJCContractRenewalPanel_Conditional_21_Template(rf, ctx) { if (rf & 1) {
|
|
176
306
|
const _r4 = i0.ɵɵgetCurrentView();
|
|
177
|
-
i0.ɵɵelementStart(0, "input",
|
|
178
|
-
i0.ɵɵlistener("ngModelChange", function
|
|
307
|
+
i0.ɵɵelementStart(0, "input", 15);
|
|
308
|
+
i0.ɵɵlistener("ngModelChange", function MJCContractRenewalPanel_Conditional_21_Template_input_ngModelChange_0_listener($event) { i0.ɵɵrestoreView(_r4); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.Set("CancellationWindowDays", $event)); });
|
|
179
309
|
i0.ɵɵelementEnd();
|
|
180
310
|
} if (rf & 2) {
|
|
181
311
|
const ctx_r1 = i0.ɵɵnextContext();
|
|
182
312
|
i0.ɵɵproperty("ngModel", ctx_r1.Record.CancellationWindowDays);
|
|
183
313
|
} }
|
|
184
|
-
function
|
|
314
|
+
function MJCContractRenewalPanel_Conditional_22_Template(rf, ctx) { if (rf & 1) {
|
|
185
315
|
i0.ɵɵelementStart(0, "div", 6);
|
|
186
316
|
i0.ɵɵtext(1);
|
|
187
317
|
i0.ɵɵelementEnd();
|
|
188
318
|
} if (rf & 2) {
|
|
189
319
|
const ctx_r1 = i0.ɵɵnextContext();
|
|
190
320
|
i0.ɵɵadvance();
|
|
191
|
-
i0.ɵɵtextInterpolate(ctx_r1.
|
|
321
|
+
i0.ɵɵtextInterpolate(ctx_r1.Days(ctx_r1.Record.CancellationWindowDays));
|
|
192
322
|
} }
|
|
193
|
-
function
|
|
194
|
-
i0.ɵɵelementStart(0, "div",
|
|
323
|
+
function MJCContractRenewalPanel_Conditional_25_Template(rf, ctx) { if (rf & 1) {
|
|
324
|
+
i0.ɵɵelementStart(0, "div", 8);
|
|
195
325
|
i0.ɵɵtext(1, "the window is open now");
|
|
196
326
|
i0.ɵɵelementEnd();
|
|
197
327
|
} }
|
|
198
|
-
function
|
|
328
|
+
function MJCContractRenewalPanel_Conditional_29_Template(rf, ctx) { if (rf & 1) {
|
|
199
329
|
const _r5 = i0.ɵɵgetCurrentView();
|
|
200
|
-
i0.ɵɵelementStart(0, "input",
|
|
201
|
-
i0.ɵɵlistener("ngModelChange", function
|
|
330
|
+
i0.ɵɵelementStart(0, "input", 16);
|
|
331
|
+
i0.ɵɵlistener("ngModelChange", function MJCContractRenewalPanel_Conditional_29_Template_input_ngModelChange_0_listener($event) { i0.ɵɵrestoreView(_r5); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.Set("AnnualIncreasePercent", $event)); });
|
|
202
332
|
i0.ɵɵelementEnd();
|
|
203
333
|
} if (rf & 2) {
|
|
204
334
|
const ctx_r1 = i0.ɵɵnextContext();
|
|
205
335
|
i0.ɵɵproperty("ngModel", ctx_r1.Record.AnnualIncreasePercent);
|
|
206
336
|
} }
|
|
207
|
-
function
|
|
337
|
+
function MJCContractRenewalPanel_Conditional_30_Template(rf, ctx) { if (rf & 1) {
|
|
208
338
|
i0.ɵɵelementStart(0, "div", 6);
|
|
209
339
|
i0.ɵɵtext(1);
|
|
210
340
|
i0.ɵɵelementEnd();
|
|
211
341
|
} if (rf & 2) {
|
|
212
342
|
const ctx_r1 = i0.ɵɵnextContext();
|
|
213
343
|
i0.ɵɵadvance();
|
|
214
|
-
i0.ɵɵtextInterpolate(ctx_r1.
|
|
344
|
+
i0.ɵɵtextInterpolate(ctx_r1.Percent(ctx_r1.Record.AnnualIncreasePercent));
|
|
215
345
|
} }
|
|
216
|
-
function
|
|
217
|
-
i0.ɵɵelementStart(0, "div",
|
|
218
|
-
i0.ɵɵtext(1, "
|
|
346
|
+
function MJCContractRenewalPanel_Conditional_31_Template(rf, ctx) { if (rf & 1) {
|
|
347
|
+
i0.ɵɵelementStart(0, "div", 11);
|
|
348
|
+
i0.ɵɵtext(1, "No renewal terms recorded.");
|
|
219
349
|
i0.ɵɵelementEnd();
|
|
220
350
|
} }
|
|
221
351
|
function MJCContractDatesPanel_Conditional_6_Template(rf, ctx) { if (rf & 1) {
|
|
222
352
|
const _r1 = i0.ɵɵgetCurrentView();
|
|
223
|
-
i0.ɵɵelementStart(0, "input",
|
|
353
|
+
i0.ɵɵelementStart(0, "input", 11);
|
|
224
354
|
i0.ɵɵlistener("ngModelChange", function MJCContractDatesPanel_Conditional_6_Template_input_ngModelChange_0_listener($event) { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.SetDate("ExecutedDate", $event)); });
|
|
225
355
|
i0.ɵɵelementEnd();
|
|
226
356
|
} if (rf & 2) {
|
|
@@ -237,16 +367,16 @@ function MJCContractDatesPanel_Conditional_7_Template(rf, ctx) { if (rf & 1) {
|
|
|
237
367
|
i0.ɵɵadvance();
|
|
238
368
|
i0.ɵɵtextInterpolate(i0.ɵɵpipeBind2(2, 1, ctx_r1.Record.ExecutedDate, "d MMM y") || "\u2014");
|
|
239
369
|
} }
|
|
240
|
-
function
|
|
370
|
+
function MJCContractDatesPanel_Conditional_11_Template(rf, ctx) { if (rf & 1) {
|
|
241
371
|
const _r3 = i0.ɵɵgetCurrentView();
|
|
242
|
-
i0.ɵɵelementStart(0, "input",
|
|
243
|
-
i0.ɵɵlistener("ngModelChange", function
|
|
372
|
+
i0.ɵɵelementStart(0, "input", 12);
|
|
373
|
+
i0.ɵɵlistener("ngModelChange", function MJCContractDatesPanel_Conditional_11_Template_input_ngModelChange_0_listener($event) { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.SetDate("EffectiveDate", $event)); });
|
|
244
374
|
i0.ɵɵelementEnd();
|
|
245
375
|
} if (rf & 2) {
|
|
246
376
|
const ctx_r1 = i0.ɵɵnextContext();
|
|
247
377
|
i0.ɵɵproperty("ngModel", ctx_r1.AsInput(ctx_r1.Record.EffectiveDate));
|
|
248
378
|
} }
|
|
249
|
-
function
|
|
379
|
+
function MJCContractDatesPanel_Conditional_12_Template(rf, ctx) { if (rf & 1) {
|
|
250
380
|
i0.ɵɵelementStart(0, "div", 5);
|
|
251
381
|
i0.ɵɵtext(1);
|
|
252
382
|
i0.ɵɵpipe(2, "date");
|
|
@@ -256,16 +386,16 @@ function MJCContractDatesPanel_Conditional_14_Template(rf, ctx) { if (rf & 1) {
|
|
|
256
386
|
i0.ɵɵadvance();
|
|
257
387
|
i0.ɵɵtextInterpolate(i0.ɵɵpipeBind2(2, 1, ctx_r1.Record.EffectiveDate, "d MMM y") || "\u2014");
|
|
258
388
|
} }
|
|
259
|
-
function
|
|
389
|
+
function MJCContractDatesPanel_Conditional_16_Template(rf, ctx) { if (rf & 1) {
|
|
260
390
|
const _r4 = i0.ɵɵgetCurrentView();
|
|
261
|
-
i0.ɵɵelementStart(0, "input",
|
|
262
|
-
i0.ɵɵlistener("ngModelChange", function
|
|
391
|
+
i0.ɵɵelementStart(0, "input", 13);
|
|
392
|
+
i0.ɵɵlistener("ngModelChange", function MJCContractDatesPanel_Conditional_16_Template_input_ngModelChange_0_listener($event) { i0.ɵɵrestoreView(_r4); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.SetDate("EndDate", $event)); });
|
|
263
393
|
i0.ɵɵelementEnd();
|
|
264
394
|
} if (rf & 2) {
|
|
265
395
|
const ctx_r1 = i0.ɵɵnextContext();
|
|
266
396
|
i0.ɵɵproperty("ngModel", ctx_r1.AsInput(ctx_r1.Record.EndDate));
|
|
267
397
|
} }
|
|
268
|
-
function
|
|
398
|
+
function MJCContractDatesPanel_Conditional_17_Template(rf, ctx) { if (rf & 1) {
|
|
269
399
|
i0.ɵɵelementStart(0, "div", 5);
|
|
270
400
|
i0.ɵɵtext(1);
|
|
271
401
|
i0.ɵɵpipe(2, "date");
|
|
@@ -275,25 +405,16 @@ function MJCContractDatesPanel_Conditional_19_Template(rf, ctx) { if (rf & 1) {
|
|
|
275
405
|
i0.ɵɵadvance();
|
|
276
406
|
i0.ɵɵtextInterpolate(i0.ɵɵpipeBind2(2, 1, ctx_r1.Record.EndDate, "d MMM y") || "\u2014");
|
|
277
407
|
} }
|
|
278
|
-
function
|
|
279
|
-
i0.ɵɵelementStart(0, "div", 6);
|
|
280
|
-
i0.ɵɵtext(1);
|
|
281
|
-
i0.ɵɵelementEnd();
|
|
282
|
-
} if (rf & 2) {
|
|
283
|
-
const ctx_r1 = i0.ɵɵnextContext();
|
|
284
|
-
i0.ɵɵadvance();
|
|
285
|
-
i0.ɵɵtextInterpolate(ctx_r1.EndsInText);
|
|
286
|
-
} }
|
|
287
|
-
function MJCContractDatesPanel_Conditional_24_Template(rf, ctx) { if (rf & 1) {
|
|
408
|
+
function MJCContractDatesPanel_Conditional_21_Template(rf, ctx) { if (rf & 1) {
|
|
288
409
|
const _r5 = i0.ɵɵgetCurrentView();
|
|
289
|
-
i0.ɵɵelementStart(0, "input",
|
|
290
|
-
i0.ɵɵlistener("ngModelChange", function
|
|
410
|
+
i0.ɵɵelementStart(0, "input", 14);
|
|
411
|
+
i0.ɵɵlistener("ngModelChange", function MJCContractDatesPanel_Conditional_21_Template_input_ngModelChange_0_listener($event) { i0.ɵɵrestoreView(_r5); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.SetDate("TerminatedDate", $event)); });
|
|
291
412
|
i0.ɵɵelementEnd();
|
|
292
413
|
} if (rf & 2) {
|
|
293
414
|
const ctx_r1 = i0.ɵɵnextContext();
|
|
294
415
|
i0.ɵɵproperty("ngModel", ctx_r1.AsInput(ctx_r1.Record.TerminatedDate));
|
|
295
416
|
} }
|
|
296
|
-
function
|
|
417
|
+
function MJCContractDatesPanel_Conditional_22_Template(rf, ctx) { if (rf & 1) {
|
|
297
418
|
i0.ɵɵelementStart(0, "div", 5);
|
|
298
419
|
i0.ɵɵtext(1);
|
|
299
420
|
i0.ɵɵpipe(2, "date");
|
|
@@ -328,9 +449,10 @@ function MJCContractLineagePanel_Conditional_2_Template(rf, ctx) { if (rf & 1) {
|
|
|
328
449
|
} }
|
|
329
450
|
function MJCContractLineagePanel_Conditional_4_Template(rf, ctx) { if (rf & 1) {
|
|
330
451
|
i0.ɵɵelementStart(0, "div", 3);
|
|
331
|
-
i0.ɵɵtext(1, "
|
|
452
|
+
i0.ɵɵtext(1, " No parent contract, change orders, or superseding contracts. ");
|
|
332
453
|
i0.ɵɵelementEnd();
|
|
333
454
|
} }
|
|
455
|
+
const COLLAPSE_SETTING = 'mj.identityHeader.collapsed.contract';
|
|
334
456
|
/** Chip variant per lifecycle state — colour carries meaning, so each state gets a considered one. */
|
|
335
457
|
function chipClassFor(state) {
|
|
336
458
|
switch (state) {
|
|
@@ -346,6 +468,23 @@ function chipClassFor(state) {
|
|
|
346
468
|
* 1 · Hero — persistent identity, above the rail
|
|
347
469
|
* ──────────────────────────────────────────────────────────────────────────── */
|
|
348
470
|
let MJCContractHeroPanel = class MJCContractHeroPanel extends BaseFormPanel {
|
|
471
|
+
cdr = inject(ChangeDetectorRef);
|
|
472
|
+
Collapsed = false;
|
|
473
|
+
ngOnInit() {
|
|
474
|
+
const raw = UserInfoEngine.Instance.GetSetting(COLLAPSE_SETTING);
|
|
475
|
+
if (raw) {
|
|
476
|
+
try {
|
|
477
|
+
this.Collapsed = JSON.parse(raw) === true;
|
|
478
|
+
}
|
|
479
|
+
catch {
|
|
480
|
+
this.Collapsed = false;
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
ToggleCollapsed() {
|
|
485
|
+
this.Collapsed = !this.Collapsed;
|
|
486
|
+
UserInfoEngine.Instance.SetSettingDebounced(COLLAPSE_SETTING, JSON.stringify(this.Collapsed));
|
|
487
|
+
}
|
|
349
488
|
/**
|
|
350
489
|
* The human name for this agreement: its description, falling back to the number.
|
|
351
490
|
*
|
|
@@ -381,9 +520,129 @@ let MJCContractHeroPanel = class MJCContractHeroPanel extends BaseFormPanel {
|
|
|
381
520
|
get CompanyName() { return this.Record?.Company ?? ''; }
|
|
382
521
|
get ContactName() { return this.Record?.PrimaryContactPerson ?? ''; }
|
|
383
522
|
get TemplateName() { return this.Record?.ContractTemplate ?? ''; }
|
|
384
|
-
|
|
523
|
+
/* ── Source record — the thing that created this contract (issue #28 item 1) ──────────────
|
|
524
|
+
*
|
|
525
|
+
* WHAT THE STAT USED TO CLAIM. Labelled "Created from", it rendered `CreatingEntity` — the name of
|
|
526
|
+
* an ENTITY, not a record — so a contract raised from a Close-Won deal read "Deals" and one
|
|
527
|
+
* entered by hand read "Entered directly". Neither told the reader WHICH deal, and the second
|
|
528
|
+
* spends a stat on the absence of a fact.
|
|
529
|
+
*
|
|
530
|
+
* `CreatingEntityID` / `CreatingRecordID` is a POLYMORPHIC pair, so nothing here may assume Deals.
|
|
531
|
+
* Today `bizapps-sales` is the only writer (`LiveContractsSeam`, on Close-Won) and always stores
|
|
532
|
+
* Deals, but the column does not say so: the entity is resolved from the id, the label takes that
|
|
533
|
+
* entity's own singular name, and an Order would read "Source Order" with no edit here.
|
|
534
|
+
*
|
|
535
|
+
* NAVIGATION GOES THROUGH THIS PANEL'S OWN `open()`, the helper next added for Customer and
|
|
536
|
+
* Contact. It handles ctrl/cmd-click for a new tab and routes through `OnFormNavigate` rather
|
|
537
|
+
* than `NavigationService`, and matching it matters more than the primary-key lookup an earlier
|
|
538
|
+
* version of this did — `CompositeKey.FromID` is the convention every link in this file uses.
|
|
539
|
+
*/
|
|
540
|
+
/** Resolved once per record, lazily, on the first template read. */
|
|
541
|
+
sourceFor = null;
|
|
542
|
+
SourceLabel = 'Source record';
|
|
543
|
+
SourceName = '';
|
|
544
|
+
/** Set when the provenance names a record that does not exist — the stat hides rather than link. */
|
|
545
|
+
SourceMissing = false;
|
|
546
|
+
/**
|
|
547
|
+
* Whether this contract records what created it.
|
|
548
|
+
*
|
|
549
|
+
* Doubles as the load trigger — `BaseFormPanel` has no lifecycle hook and the slot host sets
|
|
550
|
+
* `Record` before view init, so the first template read is the earliest reliable moment. Keyed on
|
|
551
|
+
* the record so navigating the form to another contract reloads instead of showing the previous
|
|
552
|
+
* one's deal.
|
|
553
|
+
*/
|
|
554
|
+
get HasSource() {
|
|
555
|
+
const entityID = this.Record?.CreatingEntityID;
|
|
556
|
+
const recordID = this.Record?.CreatingRecordID;
|
|
557
|
+
if (!entityID || !recordID)
|
|
558
|
+
return false;
|
|
559
|
+
const key = `${this.Record?.ID}:${entityID}:${recordID}`;
|
|
560
|
+
if (this.sourceFor !== key) {
|
|
561
|
+
this.sourceFor = key;
|
|
562
|
+
this.SourceMissing = false;
|
|
563
|
+
void this.loadSource(key);
|
|
564
|
+
}
|
|
565
|
+
return !this.SourceMissing;
|
|
566
|
+
}
|
|
567
|
+
/** The entity named by `CreatingEntityID`, or null when the id names nothing this user can see. */
|
|
568
|
+
sourceEntity() {
|
|
569
|
+
const id = this.Record?.CreatingEntityID;
|
|
570
|
+
return (id ? this.FormComponent?.ProviderToUse?.Entities?.find((e) => e.ID === id) : undefined) ?? null;
|
|
571
|
+
}
|
|
572
|
+
/**
|
|
573
|
+
* Label from the entity, name from the record.
|
|
574
|
+
*
|
|
575
|
+
* `BaseTableDisplayName` rather than `DisplayName`: the entity is plural ("Deals") and the stat
|
|
576
|
+
* labels one record, so the singular base table is the honest word — and it is what produces
|
|
577
|
+
* "Source Deal" and "Source Order" with no de-pluralising guess.
|
|
578
|
+
*/
|
|
579
|
+
async loadSource(key) {
|
|
580
|
+
const entity = this.sourceEntity();
|
|
581
|
+
if (!entity)
|
|
582
|
+
return;
|
|
583
|
+
this.SourceLabel = `Source ${entity.BaseTableDisplayName}`;
|
|
584
|
+
const nameField = entity.NameField?.Name;
|
|
585
|
+
const recordID = String(this.Record?.CreatingRecordID ?? '');
|
|
586
|
+
if (!nameField || !recordID) {
|
|
587
|
+
this.cdr.detectChanges();
|
|
588
|
+
return;
|
|
589
|
+
}
|
|
590
|
+
try {
|
|
591
|
+
const { ScopedRunView } = await import('../data/provider');
|
|
592
|
+
const rv = ScopedRunView(this.FormComponent?.ProviderToUse);
|
|
593
|
+
const pkField = entity.PrimaryKeys?.[0]?.Name ?? 'ID';
|
|
594
|
+
const r = await rv.RunView({
|
|
595
|
+
EntityName: entity.Name,
|
|
596
|
+
Fields: [nameField],
|
|
597
|
+
ExtraFilter: `${pkField} = '${recordID.replace(/'/g, "''")}'`,
|
|
598
|
+
ResultType: 'simple',
|
|
599
|
+
});
|
|
600
|
+
// Guard against a slower read for a PREVIOUS record landing after the form moved on.
|
|
601
|
+
if (this.sourceFor !== key)
|
|
602
|
+
return;
|
|
603
|
+
const row = r?.Success ? r.Results?.[0] : undefined;
|
|
604
|
+
if (r?.Success && !row) {
|
|
605
|
+
// READ SUCCEEDED AND MATCHED NOTHING: the provenance names a row that is not there,
|
|
606
|
+
// so there is nothing to open and the stat hides itself. This is the case the
|
|
607
|
+
// fallback below used to swallow — CTR-000026 carries a hand-typed pair whose record
|
|
608
|
+
// id is not even a UUID, and the stat rendered an "Open" button that navigated
|
|
609
|
+
// nowhere. A link that cannot work is worse than an absent stat: it invites a click
|
|
610
|
+
// and spends the reader's trust.
|
|
611
|
+
this.SourceMissing = true;
|
|
612
|
+
this.SourceName = '';
|
|
613
|
+
return;
|
|
614
|
+
}
|
|
615
|
+
this.SourceMissing = false;
|
|
616
|
+
this.SourceName = row ? String(row[nameField] ?? '') : '';
|
|
617
|
+
}
|
|
618
|
+
catch {
|
|
619
|
+
// A THROWN read is the different case, and the fallback is still right for it: the record
|
|
620
|
+
// may well exist and simply be unreadable by this user, so the link stays and the stat
|
|
621
|
+
// says "Open". Conflating the two is what made the dead button look deliberate.
|
|
622
|
+
this.SourceMissing = false;
|
|
623
|
+
this.SourceName = '';
|
|
624
|
+
}
|
|
625
|
+
finally {
|
|
626
|
+
this.cdr.detectChanges();
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
/** Open the record that created this contract, through the same helper as the other links. */
|
|
630
|
+
OpenSource(event) {
|
|
631
|
+
const entity = this.sourceEntity();
|
|
632
|
+
if (!entity)
|
|
633
|
+
return;
|
|
634
|
+
this.open(event, entity.Name, this.Record?.CreatingRecordID);
|
|
635
|
+
}
|
|
385
636
|
get IsAwaitingDocument() { return this.Record?.IsAwaitingDocument === true; }
|
|
386
637
|
get DaysToEnd() { return this.Record?.DaysToEnd ?? null; }
|
|
638
|
+
get StatusTone() {
|
|
639
|
+
switch (this.State) {
|
|
640
|
+
case 'Active':
|
|
641
|
+
case 'Executed': return 'success';
|
|
642
|
+
case 'Terminated': return 'warning';
|
|
643
|
+
default: return 'muted';
|
|
644
|
+
}
|
|
645
|
+
}
|
|
387
646
|
/** "in 16 months" reads better than "in 487 days" past a couple of months — the mockup's phrasing. */
|
|
388
647
|
get EndsInText() {
|
|
389
648
|
const d = this.DaysToEnd;
|
|
@@ -398,121 +657,76 @@ let MJCContractHeroPanel = class MJCContractHeroPanel extends BaseFormPanel {
|
|
|
398
657
|
const months = Math.round(d / 30);
|
|
399
658
|
return `in ${months} month${months === 1 ? '' : 's'}`;
|
|
400
659
|
}
|
|
660
|
+
OpenCustomer(event) {
|
|
661
|
+
this.open(event, MJC_FOREIGN_ENTITIES.Organization, this.Record?.CustomerOrganizationID);
|
|
662
|
+
}
|
|
663
|
+
OpenContact(event) {
|
|
664
|
+
this.open(event, MJC_FOREIGN_ENTITIES.Person, this.Record?.PrimaryContactPersonID);
|
|
665
|
+
}
|
|
666
|
+
open(event, entity, id) {
|
|
667
|
+
if (!id)
|
|
668
|
+
return;
|
|
669
|
+
event.preventDefault();
|
|
670
|
+
this.FormComponent.OnFormNavigate({
|
|
671
|
+
Kind: 'record',
|
|
672
|
+
EntityName: entity,
|
|
673
|
+
PrimaryKey: CompositeKey.FromID(id),
|
|
674
|
+
OpenInNewTab: event.ctrlKey || event.metaKey,
|
|
675
|
+
});
|
|
676
|
+
}
|
|
401
677
|
static ɵfac = /*@__PURE__*/ (() => { let ɵMJCContractHeroPanel_BaseFactory; return function MJCContractHeroPanel_Factory(__ngFactoryType__) { return (ɵMJCContractHeroPanel_BaseFactory || (ɵMJCContractHeroPanel_BaseFactory = i0.ɵɵgetInheritedFactory(MJCContractHeroPanel)))(__ngFactoryType__ || MJCContractHeroPanel); }; })();
|
|
402
|
-
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: MJCContractHeroPanel, selectors: [["mjc-contract-hero-panel"]], features: [i0.ɵɵInheritDefinitionFeature], decls:
|
|
403
|
-
i0.ɵɵ
|
|
404
|
-
i0.ɵɵ
|
|
405
|
-
i0.ɵɵ
|
|
406
|
-
i0.ɵɵ
|
|
407
|
-
i0.ɵɵ
|
|
408
|
-
i0.ɵɵ
|
|
409
|
-
i0.ɵɵ
|
|
410
|
-
i0.ɵɵ
|
|
411
|
-
i0.ɵɵ
|
|
412
|
-
i0.ɵɵ
|
|
413
|
-
i0.ɵɵ
|
|
414
|
-
i0.ɵɵ
|
|
415
|
-
i0.ɵɵ
|
|
416
|
-
i0.ɵɵdomElementStart(13, "div", 11)(14, "span", 12);
|
|
678
|
+
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: MJCContractHeroPanel, selectors: [["mjc-contract-hero-panel"]], features: [i0.ɵɵInheritDefinitionFeature], decls: 22, vars: 16, consts: [[1, "mjc-hero"], [1, "mjc-hero__identity"], ["aria-hidden", "true", 1, "mjc-hero__avatar"], [1, "fa-solid", "fa-file-signature"], [1, "mjc-hero__presence", 3, "title"], [1, "mjc-hero__copy"], [1, "mjc-hero__title-row"], [1, "mjc-hero__title"], [1, "mjc-hero__aka"], [1, "mjc-hero__badges"], [1, "mjc-hero__entity-chip"], [1, "mjc-chip"], [1, "mjc-chip", "mjc-chip--info"], ["title", "Standard agreement was modified", 1, "mjc-chip", "mjc-chip--warn"], ["title", "Executed agreement not attached", 1, "mjc-chip", "mjc-chip--warn"], ["type", "button", 1, "mjc-hero__toggle", 3, "click", "title"], ["aria-hidden", "true", 1, "fa-solid", "fa-triangle-exclamation"], ["aria-hidden", "true", 1, "fa-solid", "fa-file-circle-question"], [1, "mjc-hero__summary"], [1, "mjc-hero__stat"], [1, "mjc-hero__stat-label"], [1, "mjc-hero__stat-val"], ["type", "button", 1, "mjc-hero__stat-val", "is-link"], [1, "mjc-hero__next"], [1, "mjc-hero__edit"], [1, "mjc-flag"], ["type", "button", 1, "mjc-hero__stat-val", "is-link", 3, "click"], [1, "mjc-hero__next-val"], [1, "mjc-hero__field"], ["FieldName", "Description", "Type", "textarea", 3, "Record", "ShowLabel", "EditMode", "FormContext"]], template: function MJCContractHeroPanel_Template(rf, ctx) { if (rf & 1) {
|
|
679
|
+
i0.ɵɵelementStart(0, "div", 0)(1, "div", 1)(2, "div", 2);
|
|
680
|
+
i0.ɵɵelement(3, "i", 3);
|
|
681
|
+
i0.ɵɵconditionalCreate(4, MJCContractHeroPanel_Conditional_4_Template, 1, 2, "span", 4);
|
|
682
|
+
i0.ɵɵelementEnd();
|
|
683
|
+
i0.ɵɵelementStart(5, "div", 5)(6, "div", 6)(7, "h1", 7);
|
|
684
|
+
i0.ɵɵtext(8);
|
|
685
|
+
i0.ɵɵelementEnd()();
|
|
686
|
+
i0.ɵɵconditionalCreate(9, MJCContractHeroPanel_Conditional_9_Template, 2, 1, "div", 8);
|
|
687
|
+
i0.ɵɵelementStart(10, "div", 9)(11, "span", 10);
|
|
688
|
+
i0.ɵɵelement(12, "i", 3);
|
|
689
|
+
i0.ɵɵtext(13, " Contract");
|
|
690
|
+
i0.ɵɵelementEnd();
|
|
691
|
+
i0.ɵɵelementStart(14, "span", 11);
|
|
417
692
|
i0.ɵɵtext(15);
|
|
418
|
-
i0.ɵɵ
|
|
419
|
-
i0.ɵɵ
|
|
420
|
-
i0.ɵɵ
|
|
421
|
-
i0.ɵɵ
|
|
422
|
-
i0.ɵɵ
|
|
423
|
-
i0.ɵɵ
|
|
424
|
-
i0.ɵɵ
|
|
425
|
-
i0.ɵɵ
|
|
426
|
-
i0.ɵɵ
|
|
427
|
-
i0.ɵɵ
|
|
428
|
-
i0.ɵɵ
|
|
429
|
-
i0.ɵɵconditionalCreate(24, MJCContractHeroPanel_Conditional_24_Template, 4, 1, "span");
|
|
430
|
-
i0.ɵɵdomElementEnd()()();
|
|
431
|
-
i0.ɵɵdomElementStart(25, "div", 13)(26, "div", 14)(27, "span", 15);
|
|
432
|
-
i0.ɵɵtext(28, "Executed");
|
|
433
|
-
i0.ɵɵdomElementEnd();
|
|
434
|
-
i0.ɵɵdomElementStart(29, "span", 16);
|
|
435
|
-
i0.ɵɵtext(30);
|
|
436
|
-
i0.ɵɵpipe(31, "date");
|
|
437
|
-
i0.ɵɵdomElementEnd();
|
|
438
|
-
i0.ɵɵconditionalCreate(32, MJCContractHeroPanel_Conditional_32_Template, 2, 0, "span", 17);
|
|
439
|
-
i0.ɵɵdomElementEnd();
|
|
440
|
-
i0.ɵɵdomElementStart(33, "div", 14)(34, "span", 15);
|
|
441
|
-
i0.ɵɵtext(35, "Effective");
|
|
442
|
-
i0.ɵɵdomElementEnd();
|
|
443
|
-
i0.ɵɵdomElementStart(36, "span", 16);
|
|
444
|
-
i0.ɵɵtext(37);
|
|
445
|
-
i0.ɵɵpipe(38, "date");
|
|
446
|
-
i0.ɵɵdomElementEnd()();
|
|
447
|
-
i0.ɵɵdomElementStart(39, "div", 14)(40, "span", 15);
|
|
448
|
-
i0.ɵɵtext(41, "Term ends");
|
|
449
|
-
i0.ɵɵdomElementEnd();
|
|
450
|
-
i0.ɵɵdomElementStart(42, "span", 16);
|
|
451
|
-
i0.ɵɵtext(43);
|
|
452
|
-
i0.ɵɵpipe(44, "date");
|
|
453
|
-
i0.ɵɵdomElementEnd();
|
|
454
|
-
i0.ɵɵconditionalCreate(45, MJCContractHeroPanel_Conditional_45_Template, 2, 1, "span", 17);
|
|
455
|
-
i0.ɵɵdomElementEnd();
|
|
456
|
-
i0.ɵɵdomElementStart(46, "div", 14)(47, "span", 15);
|
|
457
|
-
i0.ɵɵtext(48, "Agreement");
|
|
458
|
-
i0.ɵɵdomElementEnd();
|
|
459
|
-
i0.ɵɵdomElementStart(49, "span", 16);
|
|
460
|
-
i0.ɵɵtext(50);
|
|
461
|
-
i0.ɵɵdomElementEnd();
|
|
462
|
-
i0.ɵɵconditionalCreate(51, MJCContractHeroPanel_Conditional_51_Template, 2, 0, "span", 17);
|
|
463
|
-
i0.ɵɵdomElementEnd();
|
|
464
|
-
i0.ɵɵdomElementStart(52, "div", 14)(53, "span", 15);
|
|
465
|
-
i0.ɵɵtext(54, "Created by");
|
|
466
|
-
i0.ɵɵdomElementEnd();
|
|
467
|
-
i0.ɵɵdomElementStart(55, "span", 16);
|
|
468
|
-
i0.ɵɵtext(56);
|
|
469
|
-
i0.ɵɵdomElementEnd();
|
|
470
|
-
i0.ɵɵconditionalCreate(57, MJCContractHeroPanel_Conditional_57_Template, 2, 0, "span", 17);
|
|
471
|
-
i0.ɵɵdomElementEnd()();
|
|
472
|
-
i0.ɵɵconditionalCreate(58, MJCContractHeroPanel_Conditional_58_Template, 2, 0, "div", 18);
|
|
473
|
-
i0.ɵɵdomElementEnd();
|
|
693
|
+
i0.ɵɵelementEnd();
|
|
694
|
+
i0.ɵɵconditionalCreate(16, MJCContractHeroPanel_Conditional_16_Template, 2, 1, "span", 12);
|
|
695
|
+
i0.ɵɵconditionalCreate(17, MJCContractHeroPanel_Conditional_17_Template, 3, 0, "span", 13);
|
|
696
|
+
i0.ɵɵconditionalCreate(18, MJCContractHeroPanel_Conditional_18_Template, 3, 0, "span", 14);
|
|
697
|
+
i0.ɵɵelementEnd()();
|
|
698
|
+
i0.ɵɵelementStart(19, "button", 15);
|
|
699
|
+
i0.ɵɵlistener("click", function MJCContractHeroPanel_Template_button_click_19_listener() { return ctx.ToggleCollapsed(); });
|
|
700
|
+
i0.ɵɵelement(20, "i");
|
|
701
|
+
i0.ɵɵelementEnd()();
|
|
702
|
+
i0.ɵɵconditionalCreate(21, MJCContractHeroPanel_Conditional_21_Template, 43, 20);
|
|
703
|
+
i0.ɵɵelementEnd();
|
|
474
704
|
} if (rf & 2) {
|
|
475
|
-
i0.ɵɵ
|
|
705
|
+
i0.ɵɵclassProp("mjc-hero--collapsed", ctx.Collapsed);
|
|
706
|
+
i0.ɵɵadvance(4);
|
|
707
|
+
i0.ɵɵconditional(!ctx.EditMode ? 4 : -1);
|
|
708
|
+
i0.ɵɵadvance(4);
|
|
476
709
|
i0.ɵɵtextInterpolate(ctx.Title);
|
|
477
710
|
i0.ɵɵadvance();
|
|
711
|
+
i0.ɵɵconditional(ctx.Record.ContractNumber && !ctx.Collapsed ? 9 : -1);
|
|
712
|
+
i0.ɵɵadvance(5);
|
|
478
713
|
i0.ɵɵclassMap("mjc-chip " + ctx.StateChipClass);
|
|
479
714
|
i0.ɵɵadvance();
|
|
480
715
|
i0.ɵɵtextInterpolate(ctx.State);
|
|
481
716
|
i0.ɵɵadvance();
|
|
482
|
-
i0.ɵɵconditional(ctx.TypeName ?
|
|
717
|
+
i0.ɵɵconditional(ctx.TypeName ? 16 : -1);
|
|
483
718
|
i0.ɵɵadvance();
|
|
484
|
-
i0.ɵɵconditional(ctx.Record.HasModifications ?
|
|
719
|
+
i0.ɵɵconditional(ctx.Record.HasModifications ? 17 : -1);
|
|
485
720
|
i0.ɵɵadvance();
|
|
486
|
-
i0.ɵɵconditional(ctx.IsAwaitingDocument ?
|
|
487
|
-
i0.ɵɵadvance(3);
|
|
488
|
-
i0.ɵɵtextInterpolate(ctx.Record.ContractNumber || "Unnumbered");
|
|
489
|
-
i0.ɵɵadvance(4);
|
|
490
|
-
i0.ɵɵtextInterpolate(ctx.CustomerName || "\u2014");
|
|
491
|
-
i0.ɵɵadvance(4);
|
|
492
|
-
i0.ɵɵtextInterpolate(ctx.CompanyName || "\u2014");
|
|
721
|
+
i0.ɵɵconditional(ctx.IsAwaitingDocument ? 18 : -1);
|
|
493
722
|
i0.ɵɵadvance();
|
|
494
|
-
i0.ɵɵ
|
|
495
|
-
i0.ɵɵ
|
|
496
|
-
i0.ɵɵtextInterpolate(i0.ɵɵpipeBind2(31, 21, ctx.Record.ExecutedDate, "d MMM y") || "\u2014");
|
|
497
|
-
i0.ɵɵadvance(2);
|
|
498
|
-
i0.ɵɵconditional(!ctx.Record.ExecutedDate ? 32 : -1);
|
|
499
|
-
i0.ɵɵadvance(5);
|
|
500
|
-
i0.ɵɵtextInterpolate(i0.ɵɵpipeBind2(38, 24, ctx.Record.EffectiveDate, "d MMM y") || "\u2014");
|
|
501
|
-
i0.ɵɵadvance(6);
|
|
502
|
-
i0.ɵɵtextInterpolate(i0.ɵɵpipeBind2(44, 27, ctx.Record.EndDate, "d MMM y") || "\u2014");
|
|
503
|
-
i0.ɵɵadvance(2);
|
|
504
|
-
i0.ɵɵconditional(ctx.DaysToEnd !== null ? 45 : -1);
|
|
505
|
-
i0.ɵɵadvance(5);
|
|
506
|
-
i0.ɵɵtextInterpolate(ctx.TemplateName || "\u2014");
|
|
507
|
-
i0.ɵɵadvance();
|
|
508
|
-
i0.ɵɵconditional(!ctx.TemplateName ? 51 : -1);
|
|
509
|
-
i0.ɵɵadvance(5);
|
|
510
|
-
i0.ɵɵtextInterpolate(ctx.CreatingEntityName || "\u2014");
|
|
723
|
+
i0.ɵɵproperty("title", ctx.Collapsed ? "Expand header" : "Collapse header");
|
|
724
|
+
i0.ɵɵattribute("aria-label", ctx.Collapsed ? "Expand header" : "Collapse header");
|
|
511
725
|
i0.ɵɵadvance();
|
|
512
|
-
i0.ɵɵ
|
|
726
|
+
i0.ɵɵclassMap(ctx.Collapsed ? "fa-solid fa-chevron-down" : "fa-solid fa-chevron-up");
|
|
513
727
|
i0.ɵɵadvance();
|
|
514
|
-
i0.ɵɵconditional(!ctx.
|
|
515
|
-
} }, dependencies: [CommonModule, BaseFormsModule, i1.DatePipe], encapsulation: 2 });
|
|
728
|
+
i0.ɵɵconditional(!ctx.Collapsed ? 21 : -1);
|
|
729
|
+
} }, dependencies: [CommonModule, BaseFormsModule, i1.MjFormFieldComponent, i2.DatePipe], styles: ["/**\n * contracts-kit.css \u2014 ported from design-docs/ui-design/mockups-v2/tokens.css.\n *\n * \u26A0 SEMANTIC TOKENS ONLY. MJ's design-token rule is explicit: *\"NEVER use primitive tokens\n * (`--mj-color-neutral-*`, `--mj-color-brand-*`) in component CSS. Primitives don't adapt to dark\n * mode.\"* An earlier version of this file used twelve of them, because the mockup did \u2014 and in a\n * standalone mockup page that is harmless, since there is no dark mode to adapt to. Ported into a real\n * component stylesheet it means every tinted surface, chip and clause box keeps its LIGHT colour when\n * the app is themed dark. That is the theming break, and it is invisible until someone switches theme.\n *\n * The mapping applied: neutral-50 \u2192 bg-surface-sunken, neutral-100 \u2192 border-subtle, neutral-300 \u2192\n * border-strong, success/error/warning-50 \u2192 status-*-bg, success/error-700 \u2192 status-*-text, brand-50 \u2192\n * status-info-bg, brand-100 \u2192 status-info-border, brand-700/900 \u2192 status-info-text. `#fff` on a brand\n * fill \u2192 `--mj-brand-on-primary`.\n *\n * THE MOCKUPS ARE THE SPEC, and this file exists to keep them so. An earlier version of this kit was\n * written from MEMORY of them, and it was wrong in a way that is invisible in source and obvious on\n * screen: it used token names that do not exist. `--mj-font-size-sm`, `--mj-text-tertiary`,\n * `--mj-color-warning-text`, `--mj-color-success-border` and four others are not MJ tokens (the real\n * names are `--mj-text-sm`, `--mj-status-warning-text`, `--mj-status-success`, \u2026). Every one of those\n * resolved to NOTHING \u2014 so font sizes fell back to browser defaults and the state chips rendered with\n * no colour at all. That is most of what \"looks bad\" was.\n *\n * So: class names and rules below are the mockup's, verbatim where possible, and **every token used\n * here has been checked to exist in MJ's `_tokens.scss`.** If you add a rule, check the token first \u2014\n * a missing custom property fails silently, which is the worst failure mode CSS has.\n *\n * SHIPPED VIA THE SECTION SHELL (`styleUrls` + `ViewEncapsulation.None`). `ngc` only compiles what a\n * component references, so a stylesheet nothing references is built into dist and never loaded.\n * `None` is required, not lazy: these classes are used by DESCENDANT components.\n *\n * Prefix note: the mockup used bare class names (`.panel`, `.chip`) because it was a standalone page.\n * Here everything is `mjc-` prefixed \u2014 bare `.panel` inside a real Explorer would collide with MJ's own\n * chrome, and `ViewEncapsulation.None` means these rules are global.\n */\n\n/* \u2500\u2500 Page frame \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.mjc-page {\n display: flex;\n flex-direction: column;\n gap: var(--mj-space-4);\n padding: var(--mj-space-5);\n}\n\n/* A grid page needs a DEFINITE height: mj-explorer-entity-data-grid is height:100% outside a related\n panel, and 100% of an auto-height parent is zero \u2014 the grid renders no rows while its toolbar still\n reports the count. MJ's own source documents that symptom. `min-height: 0` on the fill slot is\n mandatory: a flex child defaults to min-height:auto and refuses to shrink, so without it the grid\n pushes the page taller instead of scrolling inside itself. */\n.mjc-page--grid { height: 100%; min-height: 0; }\n.mjc-grid-fill { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }\n\n/* Intro prose. Constrained measure \u2014 text stops being readable much past this \u2014 and it is a real\n block with real spacing, not a bare text node floating between cards. */\n.mjc-page__intro {\n color: var(--mj-text-secondary);\n font-size: var(--mj-text-sm);\n line-height: 1.55;\n margin: 0;\n max-width: 78ch;\n}\n\n/* \u2500\u2500 Panel body helpers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n Our panels are real `<mj-collapsible-panel>`s, so MJ paints the frame, the header and the spacing.\n These classes style only what goes INSIDE one. */\n\n.mjc-body { padding: var(--mj-space-4); }\n.mjc-body--flush { padding: 0; } /* a table fills the panel edge to edge */\n.mjc-body > * + * { margin-top: var(--mj-space-3); } /* nothing ever touches its neighbour */\n\n.mjc-note {\n margin: 0;\n color: var(--mj-text-muted);\n font-size: var(--mj-text-xs);\n line-height: 1.55;\n}\n\n/* A note under a flush table needs its own padding and a rule above it, or it reads as a table row. */\n.mjc-note--footer {\n padding: var(--mj-space-3) var(--mj-space-4);\n border-top: 1px solid var(--mj-border-subtle);\n}\n\n/* \u2500\u2500 Hero (mockup 1) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.mjc-hero {\n display: flex;\n flex-direction: column;\n gap: var(--mj-space-4);\n padding: var(--mj-space-4) var(--mj-space-5);\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-lg);\n box-shadow: var(--mj-shadow-sm);\n}\n\n.mjc-hero__identity { display: flex; align-items: center; gap: var(--mj-space-4); min-width: 0; }\n\n.mjc-hero__avatar {\n flex: none;\n width: 52px; height: 52px;\n border-radius: var(--mj-radius-md);\n display: flex; align-items: center; justify-content: center;\n background: color-mix(in srgb, var(--mj-brand-primary) 18%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n font-size: var(--mj-text-xl, 1.375rem);\n}\n\n.mjc-hero__copy { min-width: 0; flex: 1; }\n\n.mjc-hero__title-row {\n display: flex; align-items: center; flex-wrap: wrap;\n gap: var(--mj-space-2) var(--mj-space-3);\n}\n\n.mjc-hero__title {\n margin: 0;\n font-size: var(--mj-text-lg);\n font-weight: 700;\n line-height: 1.25;\n /* Long contract descriptions must not push the chips off the card. */\n overflow-wrap: anywhere;\n}\n\n.mjc-hero__meta {\n display: flex; flex-wrap: wrap;\n gap: var(--mj-space-3);\n color: var(--mj-text-secondary);\n font-size: var(--mj-text-sm);\n margin-top: var(--mj-space-2);\n}\n\n/* auto-fit so five stats sit in a row on a wide screen and reflow on a laptop, rather than\n overflowing the card \u2014 which is what a fixed five-column grid did. */\n.mjc-hero__stats {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(8.5rem, 1fr));\n gap: var(--mj-space-3);\n}\n\n.mjc-stat {\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n padding: var(--mj-space-3);\n min-width: 0;\n}\n.mjc-stat__label {\n display: block; font-size: var(--mj-text-xs);\n text-transform: uppercase; letter-spacing: .04em;\n color: var(--mj-text-muted);\n}\n.mjc-stat__value {\n display: block; font-size: var(--mj-text-base); font-weight: 700; margin-top: 2px;\n overflow-wrap: anywhere;\n}\n.mjc-stat__sub { display: block; font-size: var(--mj-text-xs); color: var(--mj-text-muted); }\n\n/* \u2500\u2500 Chips \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.mjc-chip {\n display: inline-flex; align-items: center; gap: 4px;\n font-size: var(--mj-text-xs); font-weight: 600;\n padding: 2px 9px; border-radius: 999px;\n border: 1px solid transparent; white-space: nowrap;\n}\n.mjc-chip--ok { background: var(--mj-status-success-bg); color: var(--mj-status-success-text); border-color: var(--mj-status-success); }\n.mjc-chip--warn { background: var(--mj-status-warning-bg); color: var(--mj-status-warning-text); border-color: var(--mj-status-warning); }\n.mjc-chip--error { background: var(--mj-status-error-bg); color: var(--mj-status-error-text); border-color: var(--mj-status-error); }\n.mjc-chip--info { background: var(--mj-status-info-bg); color: var(--mj-status-info-text); border-color: var(--mj-status-info-border); }\n.mjc-chip--muted { background: var(--mj-border-subtle); color: var(--mj-text-secondary); border-color: var(--mj-border-default); }\n\n/* \u2500\u2500 Buttons \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.mjc-btn {\n display: inline-flex; align-items: center; gap: 6px;\n font-size: var(--mj-text-sm); font-weight: 600;\n padding: 6px 12px;\n border-radius: var(--mj-radius-sm);\n border: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface);\n color: var(--mj-text-primary);\n cursor: pointer;\n}\n.mjc-btn:disabled { opacity: .5; cursor: default; }\n.mjc-btn--primary { background: var(--mj-brand-primary); border-color: var(--mj-brand-primary); color: var(--mj-brand-on-primary); }\n.mjc-btn--flat { background: transparent; border-color: transparent; color: var(--mj-brand-primary); }\n.mjc-btn--sm { padding: 3px 9px; font-size: var(--mj-text-xs); }\n.mjc-btn--danger { color: var(--mj-status-error-text); border-color: transparent; background: transparent; }\n\n/* \u2500\u2500 Field grid \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.mjc-fields {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));\n gap: var(--mj-space-3) var(--mj-space-4);\n}\n.mjc-field > label {\n display: block; font-size: var(--mj-text-xs); color: var(--mj-text-muted);\n text-transform: uppercase; letter-spacing: .04em; margin-bottom: 3px;\n}\n.mjc-field .mjc-val {\n padding: 6px 9px;\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-sm);\n background: var(--mj-bg-surface);\n min-height: 31px;\n overflow-wrap: anywhere;\n}\n.mjc-field .mjc-val--ro { background: var(--mj-bg-surface-sunken); color: var(--mj-text-secondary); }\n\n/* EDIT MODE MATCHES READ MODE. These panels render bare native controls -- `<input type=\"date\">`,\n `<input type=\"number\">`, `<select>` -- because the generated datetime picker shows a time\n component for a `date` column, which is the whole reason the Dates panel exists. A bare control\n inherits none of the app's typography or chrome, so the same field visibly changed font, height\n and border the moment you pressed Edit. This mirrors `.mjc-val` above, field for field, so\n toggling edit does not move anything on screen.\n\n `font: inherit` is doing real work: form controls do NOT inherit font from their ancestor by\n default in any browser -- they fall back to a UA font -- so without it the value box and the\n input disagree even when every other property matches.\n\n THE WIDTH LIVES HERE, not on each control. The panels used to carry seven inline\n `style=\"width:100%\"` attributes; they are gone, and this rule is what replaces them. */\n.mjc-field input,\n.mjc-field select {\n width: 100%;\n box-sizing: border-box;\n font: inherit;\n color: inherit;\n padding: 6px 9px;\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-sm);\n background: var(--mj-bg-surface);\n min-height: 31px;\n}\n.mjc-field input:focus-visible,\n.mjc-field select:focus-visible { outline: 2px solid var(--mj-brand-primary); outline-offset: -1px; }\n.mjc-field input:disabled,\n.mjc-field select:disabled { background: var(--mj-bg-surface-sunken); color: var(--mj-text-secondary); }\n.mjc-hint { color: var(--mj-text-muted); font-size: var(--mj-text-xs); margin-top: 3px; }\n\n/* \u2500\u2500 Tables \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n The mockup renders modifications, documents and lineage as TABLES, not stacked cards. With three\n or more rows a table is scannable and a stack is a wall. */\n\ntable.mjc-grid { width: 100%; border-collapse: collapse; }\ntable.mjc-grid th {\n text-align: left; font-size: var(--mj-text-xs);\n text-transform: uppercase; letter-spacing: .04em;\n color: var(--mj-text-muted); font-weight: 700;\n padding: var(--mj-space-2) var(--mj-space-3);\n border-bottom: 1.5px solid var(--mj-border-default);\n}\ntable.mjc-grid td {\n padding: var(--mj-space-3);\n border-bottom: 1px solid var(--mj-border-subtle);\n vertical-align: top;\n}\ntable.mjc-grid tr:last-child td { border-bottom: 0; }\ntable.mjc-grid tbody tr:hover td { background: var(--mj-bg-surface-sunken); }\n.mjc-row--click { cursor: pointer; }\n\n.mjc-muted { color: var(--mj-text-muted); }\n.mjc-mono { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: var(--mj-text-xs); }\n\n/* \u2500\u2500 The clause pair (mockups 1 and 2) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n The standard clause and what this contract says instead, read side by side. This is the app's\n central idea rendered, so it gets real styling rather than two paragraphs. */\n\n.mjc-pair {\n display: grid; grid-template-columns: 1fr; gap: var(--mj-space-3);\n margin-top: var(--mj-space-2);\n}\n/* Side by side only when there is room \u2014 two 40ch columns on a laptop is worse than one readable one. */\n@media (min-width: 1100px) { .mjc-pair { grid-template-columns: 1fr 1fr; } }\n\n.mjc-pair__tag {\n display: block; font-size: var(--mj-text-xs); font-weight: 700;\n text-transform: uppercase; letter-spacing: .04em;\n color: var(--mj-text-muted); margin-bottom: 3px;\n}\n.mjc-pair__tag--mod { color: var(--mj-status-warning-text); }\n\n.mjc-clause {\n font-size: var(--mj-text-xs);\n color: var(--mj-text-secondary);\n background: var(--mj-bg-surface-sunken);\n border-left: 2px solid var(--mj-border-strong);\n padding: var(--mj-space-2) var(--mj-space-3);\n border-radius: 0 var(--mj-radius-sm) var(--mj-radius-sm) 0;\n margin: 0;\n /* Clause text carries its own line breaks, and 9.1 is a single 1,100-character sentence in caps \u2014\n both must wrap inside the box rather than escaping it. */\n white-space: pre-wrap;\n overflow-wrap: anywhere;\n}\n.mjc-clause--mod {\n border-left-color: var(--mj-status-warning);\n background: var(--mj-status-warning-bg);\n color: var(--mj-text-primary);\n}\n\n.mjc-toggle {\n font-size: var(--mj-text-xs); color: var(--mj-brand-primary);\n font-weight: 600; margin-top: 4px; background: none; border: 0; padding: 0; cursor: pointer;\n}\n\n/* \u2500\u2500 Callout \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.mjc-flag {\n background: var(--mj-status-warning-bg);\n border-left: 3px solid var(--mj-status-warning);\n padding: var(--mj-space-2) var(--mj-space-3);\n font-size: var(--mj-text-xs);\n color: var(--mj-status-warning-text);\n border-radius: 0 var(--mj-radius-sm) var(--mj-radius-sm) 0;\n line-height: 1.55;\n}\n\n/* \u2500\u2500 Invalid input \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n/* A required field the user has emptied. Border + ring only \u2014 no background change, because these\n are prose textareas and tinting the reading surface makes the text itself harder to read, which\n is the opposite of helpful when the point is \"write something here\". Tokens only, per the\n design-token gate. */\n.mjc-invalid {\n border-color: var(--mj-status-error) !important;\n box-shadow: 0 0 0 2px var(--mj-status-error-bg);\n outline: none;\n}\n\n/* \u2500\u2500 Filter pills (watchlist) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.mjc-pills { display: flex; flex-wrap: wrap; gap: var(--mj-space-2); align-items: center; }\n\n.mjc-pill {\n appearance: none; cursor: pointer;\n border: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface);\n color: var(--mj-text-secondary);\n border-radius: 999px;\n padding: 3px var(--mj-space-3);\n font-size: var(--mj-text-sm);\n line-height: 1.6;\n display: inline-flex; align-items: center; gap: var(--mj-space-2);\n}\n.mjc-pill:hover { border-color: var(--mj-brand-primary); color: var(--mj-text-primary); }\n.mjc-pill:disabled { opacity: .5; cursor: default; }\n.mjc-pill--active {\n background: var(--mj-status-info-bg);\n border-color: var(--mj-brand-primary);\n color: var(--mj-status-info-text);\n font-weight: 700;\n}\n.mjc-pill__count { font-variant-numeric: tabular-nums; opacity: .85; font-size: var(--mj-text-xs); }\n\n/* \u2500\u2500 Dashboard command center \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.mjc-kpis {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));\n gap: var(--mj-space-3);\n}\n.mjc-kpi {\n appearance: none;\n font: inherit;\n text-align: left;\n color: inherit;\n cursor: pointer;\n padding: var(--mj-space-3) var(--mj-space-4);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n background: var(--mj-bg-surface);\n}\n.mjc-kpi:hover { border-color: var(--mj-brand-primary); }\n.mjc-kpi:disabled { opacity: .6; cursor: default; }\n.mjc-kpi--alert .mjc-kpi__v { color: var(--mj-status-error-text); }\n.mjc-kpi__l {\n font-size: var(--mj-text-xs);\n font-weight: 700;\n text-transform: uppercase;\n letter-spacing: .04em;\n color: var(--mj-text-muted);\n}\n.mjc-kpi__v {\n font-size: var(--mj-text-xl, 1.35rem);\n font-weight: 700;\n margin: 4px 0 2px;\n font-variant-numeric: tabular-nums;\n}\n.mjc-kpi__f {\n font-size: var(--mj-text-xs);\n color: var(--mj-text-secondary);\n line-height: 1.35;\n}\n\n.mjc-dash-split {\n display: grid;\n grid-template-columns: 1.15fr .85fr;\n gap: var(--mj-space-3);\n}\n@media (max-width: 900px) { .mjc-dash-split { grid-template-columns: 1fr; } }\n\n.mjc-dash-card {\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n overflow: hidden;\n}\n.mjc-dash-card__h {\n display: flex;\n justify-content: space-between;\n gap: var(--mj-space-2);\n align-items: baseline;\n padding: var(--mj-space-3) var(--mj-space-4);\n border-bottom: 1px solid var(--mj-border-subtle);\n font-weight: 700;\n}\n.mjc-dash-card__h span {\n font-weight: 500;\n font-size: var(--mj-text-xs);\n color: var(--mj-text-muted);\n}\n\n.mjc-barlist { display: flex; flex-direction: column; gap: var(--mj-space-2); padding: var(--mj-space-3) var(--mj-space-4); }\n.mjc-barrow {\n display: grid;\n grid-template-columns: 7.5rem 1fr auto;\n gap: var(--mj-space-2);\n align-items: center;\n font-size: var(--mj-text-sm);\n}\n.mjc-track {\n height: 8px;\n background: var(--mj-bg-surface-sunken);\n border-radius: 99px;\n overflow: hidden;\n}\n.mjc-fill {\n height: 100%;\n background: var(--mj-brand-primary);\n border-radius: 99px;\n}\n.mjc-num { font-variant-numeric: tabular-nums; font-weight: 700; }\n\n.mjc-funnel {\n display: flex;\n gap: var(--mj-space-2);\n align-items: flex-end;\n height: 10rem;\n padding: var(--mj-space-3) var(--mj-space-4);\n}\n.mjc-funnel__col {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 6px;\n}\n.mjc-funnel__bar {\n width: 100%;\n min-height: 8px;\n border-radius: 8px 8px 2px 2px;\n background: var(--mj-brand-primary);\n}\n.mjc-funnel__n { font-weight: 700; }\n.mjc-funnel__lab {\n font-size: var(--mj-text-xs);\n color: var(--mj-text-muted);\n text-align: center;\n}\n\n.mjc-buckets {\n display: grid;\n grid-template-columns: repeat(4, 1fr);\n gap: var(--mj-space-2);\n padding: var(--mj-space-3) var(--mj-space-4);\n}\n@media (max-width: 700px) { .mjc-buckets { grid-template-columns: 1fr 1fr; } }\n.mjc-bucket {\n background: var(--mj-bg-page);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n padding: var(--mj-space-3);\n}\n\n.mjc-viewer-host {\n min-height: 420px;\n height: 480px;\n display: flex;\n flex-direction: column;\n}\n.mjc-viewer-host mj-entity-viewer {\n display: flex;\n flex-direction: column;\n flex: 1 1 auto;\n min-height: 350px;\n width: 100%;\n}\n\n/* \u2500\u2500 Empty state \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n A sentence in a bordered box, never a bare line of text in whitespace. */\n\n.mjc-empty {\n display: flex; align-items: center; gap: var(--mj-space-2); justify-content: center;\n padding: var(--mj-space-6);\n color: var(--mj-text-muted);\n font-size: var(--mj-text-sm);\n background: var(--mj-bg-surface-sunken);\n border: 1px dashed var(--mj-border-strong);\n border-radius: var(--mj-radius-md);\n text-align: center;\n}\n", "\n .mjc-hero {\n display: flex; flex-direction: column; gap: var(--mj-space-4);\n padding: 20px 24px; margin-bottom: var(--mj-space-4);\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-xl, 16px);\n box-shadow: var(--mj-shadow-md, 0 4px 16px rgba(0, 0, 0, .08));\n position: relative; overflow: hidden;\n }\n .mjc-hero::before {\n content: ''; position: absolute; top: 0; left: 0; right: 0; height: 3.5px;\n background: linear-gradient(90deg, #38bdf8 0%, #6366f1 50%, #10b981 100%);\n }\n .mjc-hero__identity { display: flex; align-items: center; gap: var(--mj-space-4); min-width: 0; }\n .mjc-hero__avatar {\n flex: none; width: 60px; height: 60px; border-radius: var(--mj-radius-lg, 14px);\n position: relative; display: flex; align-items: center; justify-content: center;\n background: linear-gradient(135deg, color-mix(in srgb, var(--mj-brand-primary) 30%, var(--mj-bg-surface)) 0%, color-mix(in srgb, var(--mj-brand-accent, #6366f1) 25%, var(--mj-bg-surface)) 100%);\n color: var(--mj-brand-primary); font-size: 1.35rem;\n box-shadow: 0 4px 14px color-mix(in srgb, var(--mj-brand-primary) 25%, transparent);\n border: 2px solid color-mix(in srgb, var(--mj-brand-primary) 35%, transparent);\n }\n .mjc-hero__presence {\n position: absolute; bottom: -2px; right: -2px; width: 13px; height: 13px;\n border-radius: 50%; border: 2.5px solid var(--mj-bg-surface-card);\n background: var(--mj-text-muted, #94a3b8);\n }\n .mjc-hero__presence[data-tone='success'] { background: var(--mj-status-success, #10b981); }\n .mjc-hero__presence[data-tone='warning'] { background: var(--mj-status-warning, #f59e0b); }\n .mjc-hero__copy { min-width: 0; flex: 1; }\n .mjc-hero__title {\n margin: 0; font-size: var(--mj-text-lg, 18px); font-weight: 800;\n letter-spacing: -.02em; line-height: 1.25; color: var(--mj-text-primary);\n overflow-wrap: anywhere;\n }\n .mjc-hero__aka { margin-top: 2px; font-size: var(--mj-text-xs); color: var(--mj-text-muted); }\n .mjc-hero__badges {\n display: flex; align-items: center; flex-wrap: wrap;\n gap: var(--mj-space-2); margin-top: var(--mj-space-2);\n }\n .mjc-hero__entity-chip {\n display: inline-flex; align-items: center; gap: 4px; padding: 2px 8px;\n border-radius: var(--mj-radius-sm);\n background: var(--mj-status-info-bg); color: var(--mj-brand-primary);\n font-size: var(--mj-text-xs); font-weight: 650;\n }\n .mjc-hero__toggle {\n display: inline-flex; align-items: center; justify-content: center;\n flex: none; width: 32px; height: 32px; margin-left: auto; padding: 0;\n border: 1px solid var(--mj-border-default); border-radius: var(--mj-radius-md, 8px);\n background: var(--mj-bg-surface-sunken, rgba(255,255,255,.04));\n color: var(--mj-text-secondary); cursor: pointer; font-size: 12px;\n }\n .mjc-hero__toggle:hover {\n background: var(--mj-bg-surface-hover, rgba(255,255,255,.08));\n color: var(--mj-text-primary); border-color: var(--mj-brand-primary);\n }\n .mjc-hero__summary {\n display: grid; grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));\n gap: var(--mj-space-3); padding-top: var(--mj-space-4);\n border-top: 1px solid var(--mj-border-default);\n }\n .mjc-hero__stat { display: flex; flex-direction: column; gap: 3px; min-width: 0; }\n .mjc-hero__stat-label {\n font-size: var(--mj-text-xs); font-weight: 700; letter-spacing: .04em;\n text-transform: uppercase; color: var(--mj-text-muted);\n }\n .mjc-hero__stat-val {\n font-size: 15px; font-weight: 650; color: var(--mj-text-primary);\n overflow: hidden; text-overflow: ellipsis; white-space: nowrap;\n }\n button.mjc-hero__stat-val, .mjc-hero__stat-val.is-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 button.mjc-hero__stat-val:hover { text-decoration: underline; }\n .mjc-hero__next {\n display: flex; flex-wrap: wrap; align-items: baseline; gap: 8px 14px;\n padding: var(--mj-space-3) var(--mj-space-4);\n background: var(--mj-bg-page); border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n }\n .mjc-hero__next-val { font-weight: 700; font-size: 15px; }\n .mjc-hero__edit {\n display: flex; flex-direction: column; gap: var(--mj-space-3);\n padding-top: var(--mj-space-3); border-top: 1px solid var(--mj-border-subtle, var(--mj-border-default));\n }\n .mjc-hero__field { min-width: 0; }\n .mjc-hero__field .mj-forms-field {\n display: flex; flex-direction: column; align-items: stretch; gap: 4px; padding: 0;\n }\n .mjc-hero__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 .mjc-hero--collapsed { padding: 12px 20px; gap: 0; margin-bottom: var(--mj-space-3); }\n .mjc-hero--collapsed .mjc-hero__avatar { width: 42px; height: 42px; border-radius: var(--mj-radius-md, 10px); font-size: 1.05rem; }\n .mjc-hero--collapsed .mjc-hero__title { font-size: 1.15rem; }\n @media (max-width: 720px) {\n .mjc-hero__identity { align-items: flex-start; }\n .mjc-hero__summary { grid-template-columns: repeat(2, minmax(0, 1fr)); }\n }\n "], encapsulation: 2 });
|
|
516
730
|
};
|
|
517
731
|
MJCContractHeroPanel = __decorate([
|
|
518
732
|
RegisterClassEx(BaseFormPanel, {
|
|
@@ -529,84 +743,158 @@ MJCContractHeroPanel = __decorate([
|
|
|
529
743
|
export { MJCContractHeroPanel };
|
|
530
744
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(MJCContractHeroPanel, [{
|
|
531
745
|
type: Component,
|
|
532
|
-
args: [{
|
|
533
|
-
|
|
534
|
-
standalone: true,
|
|
535
|
-
encapsulation: ViewEncapsulation.None,
|
|
536
|
-
imports: [CommonModule, BaseFormsModule],
|
|
537
|
-
template: `
|
|
538
|
-
<div class="mjc-hero">
|
|
746
|
+
args: [{ selector: 'mjc-contract-hero-panel', standalone: true, encapsulation: ViewEncapsulation.None, imports: [CommonModule, BaseFormsModule], template: `
|
|
747
|
+
<div class="mjc-hero" [class.mjc-hero--collapsed]="Collapsed">
|
|
539
748
|
<div class="mjc-hero__identity">
|
|
540
|
-
<div class="mjc-hero__avatar"
|
|
749
|
+
<div class="mjc-hero__avatar" aria-hidden="true">
|
|
750
|
+
<i class="fa-solid fa-file-signature"></i>
|
|
751
|
+
@if (!EditMode) {
|
|
752
|
+
<span class="mjc-hero__presence" [attr.data-tone]="StatusTone" [title]="State"></span>
|
|
753
|
+
}
|
|
754
|
+
</div>
|
|
541
755
|
<div class="mjc-hero__copy">
|
|
542
756
|
<div class="mjc-hero__title-row">
|
|
543
757
|
<h1 class="mjc-hero__title">{{ Title }}</h1>
|
|
758
|
+
</div>
|
|
759
|
+
@if (Record.ContractNumber && !Collapsed) {
|
|
760
|
+
<div class="mjc-hero__aka">{{ Record.ContractNumber }}</div>
|
|
761
|
+
}
|
|
762
|
+
<div class="mjc-hero__badges">
|
|
763
|
+
<span class="mjc-hero__entity-chip"><i class="fa-solid fa-file-signature"></i> Contract</span>
|
|
544
764
|
<span class="mjc-chip" [class]="'mjc-chip ' + StateChipClass">{{ State }}</span>
|
|
545
765
|
@if (TypeName) { <span class="mjc-chip mjc-chip--info">{{ TypeName }}</span> }
|
|
546
766
|
@if (Record.HasModifications) {
|
|
547
767
|
<span class="mjc-chip mjc-chip--warn"
|
|
548
|
-
title="
|
|
768
|
+
title="Standard agreement was modified">
|
|
549
769
|
<i class="fa-solid fa-triangle-exclamation" aria-hidden="true"></i> Agreement modified
|
|
550
770
|
</span>
|
|
551
771
|
}
|
|
552
772
|
@if (IsAwaitingDocument) {
|
|
553
773
|
<span class="mjc-chip mjc-chip--warn"
|
|
554
|
-
title="
|
|
774
|
+
title="Executed agreement not attached">
|
|
555
775
|
<i class="fa-solid fa-file-circle-question" aria-hidden="true"></i> Awaiting document
|
|
556
776
|
</span>
|
|
557
777
|
}
|
|
558
778
|
</div>
|
|
559
|
-
<div class="mjc-hero__meta">
|
|
560
|
-
<span class="mjc-mono">{{ Record.ContractNumber || 'Unnumbered' }}</span>
|
|
561
|
-
<span>Customer: <strong>{{ CustomerName || '—' }}</strong></span>
|
|
562
|
-
<span>Selling: <strong>{{ CompanyName || '—' }}</strong></span>
|
|
563
|
-
@if (ContactName) { <span>Contact: <strong>{{ ContactName }}</strong></span> }
|
|
564
|
-
</div>
|
|
565
779
|
</div>
|
|
780
|
+
<button type="button" class="mjc-hero__toggle"
|
|
781
|
+
[title]="Collapsed ? 'Expand header' : 'Collapse header'"
|
|
782
|
+
[attr.aria-label]="Collapsed ? 'Expand header' : 'Collapse header'"
|
|
783
|
+
(click)="ToggleCollapsed()">
|
|
784
|
+
<i [class]="Collapsed ? 'fa-solid fa-chevron-down' : 'fa-solid fa-chevron-up'"></i>
|
|
785
|
+
</button>
|
|
566
786
|
</div>
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
<
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
787
|
+
@if (!Collapsed) {
|
|
788
|
+
<div class="mjc-hero__summary">
|
|
789
|
+
<!--
|
|
790
|
+
OUR SIDE FIRST, AND IT IS NOT CALLED "SELLING" (#28 item 8).
|
|
791
|
+
|
|
792
|
+
CompanyID is which of OUR entities holds the agreement. Someone scanning contracts
|
|
793
|
+
orients by that before they look at who it is with, so it leads the summary rather
|
|
794
|
+
than sitting third. "Selling" was also the wrong word: the company holds the
|
|
795
|
+
contract whether or not anything is being sold.
|
|
796
|
+
-->
|
|
797
|
+
<div class="mjc-hero__stat">
|
|
798
|
+
<span class="mjc-hero__stat-label">Company</span>
|
|
799
|
+
<span class="mjc-hero__stat-val">{{ CompanyName || '—' }}</span>
|
|
800
|
+
</div>
|
|
801
|
+
<div class="mjc-hero__stat">
|
|
802
|
+
<span class="mjc-hero__stat-label">Customer</span>
|
|
803
|
+
@if (Record.CustomerOrganizationID && CustomerName) {
|
|
804
|
+
<button type="button" class="mjc-hero__stat-val is-link" (click)="OpenCustomer($event)">{{ CustomerName }}</button>
|
|
805
|
+
} @else {
|
|
806
|
+
<span class="mjc-hero__stat-val">{{ CustomerName || '—' }}</span>
|
|
807
|
+
}
|
|
808
|
+
</div>
|
|
809
|
+
<div class="mjc-hero__stat">
|
|
810
|
+
<span class="mjc-hero__stat-label">Contact</span>
|
|
811
|
+
@if (Record.PrimaryContactPersonID && ContactName) {
|
|
812
|
+
<button type="button" class="mjc-hero__stat-val is-link" (click)="OpenContact($event)">{{ ContactName }}</button>
|
|
813
|
+
} @else {
|
|
814
|
+
<span class="mjc-hero__stat-val">{{ ContactName || '—' }}</span>
|
|
815
|
+
}
|
|
816
|
+
</div>
|
|
817
|
+
<div class="mjc-hero__stat">
|
|
818
|
+
<span class="mjc-hero__stat-label">Executed</span>
|
|
819
|
+
<span class="mjc-hero__stat-val">{{ (Record.ExecutedDate | date: 'd MMM y') || '—' }}</span>
|
|
820
|
+
</div>
|
|
821
|
+
<div class="mjc-hero__stat">
|
|
822
|
+
<span class="mjc-hero__stat-label">Effective</span>
|
|
823
|
+
<span class="mjc-hero__stat-val">{{ (Record.EffectiveDate | date: 'd MMM y') || '—' }}</span>
|
|
824
|
+
</div>
|
|
825
|
+
<div class="mjc-hero__stat">
|
|
826
|
+
<span class="mjc-hero__stat-label">Term ends</span>
|
|
827
|
+
<span class="mjc-hero__stat-val">{{ (Record.EndDate | date: 'd MMM y') || '—' }}</span>
|
|
828
|
+
</div>
|
|
829
|
+
<div class="mjc-hero__stat">
|
|
830
|
+
<span class="mjc-hero__stat-label">Agreement</span>
|
|
831
|
+
<span class="mjc-hero__stat-val">{{ TemplateName || '—' }}</span>
|
|
832
|
+
</div>
|
|
833
|
+
@if (HasSource) {
|
|
834
|
+
<div class="mjc-hero__stat">
|
|
835
|
+
<span class="mjc-hero__stat-label">{{ SourceLabel }}</span>
|
|
836
|
+
<button type="button" class="mjc-hero__stat-val is-link" (click)="OpenSource($event)"
|
|
837
|
+
[attr.aria-label]="'Open ' + (SourceName || 'the source record')">
|
|
838
|
+
{{ SourceName || 'Open' }}
|
|
839
|
+
</button>
|
|
840
|
+
</div>
|
|
841
|
+
}
|
|
599
842
|
</div>
|
|
843
|
+
@if (DaysToEnd !== null) {
|
|
844
|
+
<div class="mjc-hero__next">
|
|
845
|
+
<span class="mjc-hero__stat-label">Term</span>
|
|
846
|
+
<span class="mjc-hero__next-val">{{ EndsInText }}</span>
|
|
847
|
+
</div>
|
|
848
|
+
}
|
|
849
|
+
@if (EditMode) {
|
|
850
|
+
<div class="mjc-hero__edit">
|
|
851
|
+
<div class="mjc-hero__field">
|
|
852
|
+
<mj-form-field [Record]="Record" [ShowLabel]="true" FieldName="Description"
|
|
853
|
+
Type="textarea" [EditMode]="EditMode" [FormContext]="FormContext"></mj-form-field>
|
|
854
|
+
</div>
|
|
855
|
+
</div>
|
|
856
|
+
}
|
|
857
|
+
@if (!Record.ContractNumber) {
|
|
858
|
+
<div class="mjc-flag">Contract number is assigned on save.</div>
|
|
859
|
+
}
|
|
600
860
|
}
|
|
601
861
|
</div>
|
|
602
|
-
`,
|
|
603
|
-
}]
|
|
862
|
+
`, styles: ["/**\n * contracts-kit.css \u2014 ported from design-docs/ui-design/mockups-v2/tokens.css.\n *\n * \u26A0 SEMANTIC TOKENS ONLY. MJ's design-token rule is explicit: *\"NEVER use primitive tokens\n * (`--mj-color-neutral-*`, `--mj-color-brand-*`) in component CSS. Primitives don't adapt to dark\n * mode.\"* An earlier version of this file used twelve of them, because the mockup did \u2014 and in a\n * standalone mockup page that is harmless, since there is no dark mode to adapt to. Ported into a real\n * component stylesheet it means every tinted surface, chip and clause box keeps its LIGHT colour when\n * the app is themed dark. That is the theming break, and it is invisible until someone switches theme.\n *\n * The mapping applied: neutral-50 \u2192 bg-surface-sunken, neutral-100 \u2192 border-subtle, neutral-300 \u2192\n * border-strong, success/error/warning-50 \u2192 status-*-bg, success/error-700 \u2192 status-*-text, brand-50 \u2192\n * status-info-bg, brand-100 \u2192 status-info-border, brand-700/900 \u2192 status-info-text. `#fff` on a brand\n * fill \u2192 `--mj-brand-on-primary`.\n *\n * THE MOCKUPS ARE THE SPEC, and this file exists to keep them so. An earlier version of this kit was\n * written from MEMORY of them, and it was wrong in a way that is invisible in source and obvious on\n * screen: it used token names that do not exist. `--mj-font-size-sm`, `--mj-text-tertiary`,\n * `--mj-color-warning-text`, `--mj-color-success-border` and four others are not MJ tokens (the real\n * names are `--mj-text-sm`, `--mj-status-warning-text`, `--mj-status-success`, \u2026). Every one of those\n * resolved to NOTHING \u2014 so font sizes fell back to browser defaults and the state chips rendered with\n * no colour at all. That is most of what \"looks bad\" was.\n *\n * So: class names and rules below are the mockup's, verbatim where possible, and **every token used\n * here has been checked to exist in MJ's `_tokens.scss`.** If you add a rule, check the token first \u2014\n * a missing custom property fails silently, which is the worst failure mode CSS has.\n *\n * SHIPPED VIA THE SECTION SHELL (`styleUrls` + `ViewEncapsulation.None`). `ngc` only compiles what a\n * component references, so a stylesheet nothing references is built into dist and never loaded.\n * `None` is required, not lazy: these classes are used by DESCENDANT components.\n *\n * Prefix note: the mockup used bare class names (`.panel`, `.chip`) because it was a standalone page.\n * Here everything is `mjc-` prefixed \u2014 bare `.panel` inside a real Explorer would collide with MJ's own\n * chrome, and `ViewEncapsulation.None` means these rules are global.\n */\n\n/* \u2500\u2500 Page frame \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.mjc-page {\n display: flex;\n flex-direction: column;\n gap: var(--mj-space-4);\n padding: var(--mj-space-5);\n}\n\n/* A grid page needs a DEFINITE height: mj-explorer-entity-data-grid is height:100% outside a related\n panel, and 100% of an auto-height parent is zero \u2014 the grid renders no rows while its toolbar still\n reports the count. MJ's own source documents that symptom. `min-height: 0` on the fill slot is\n mandatory: a flex child defaults to min-height:auto and refuses to shrink, so without it the grid\n pushes the page taller instead of scrolling inside itself. */\n.mjc-page--grid { height: 100%; min-height: 0; }\n.mjc-grid-fill { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }\n\n/* Intro prose. Constrained measure \u2014 text stops being readable much past this \u2014 and it is a real\n block with real spacing, not a bare text node floating between cards. */\n.mjc-page__intro {\n color: var(--mj-text-secondary);\n font-size: var(--mj-text-sm);\n line-height: 1.55;\n margin: 0;\n max-width: 78ch;\n}\n\n/* \u2500\u2500 Panel body helpers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n Our panels are real `<mj-collapsible-panel>`s, so MJ paints the frame, the header and the spacing.\n These classes style only what goes INSIDE one. */\n\n.mjc-body { padding: var(--mj-space-4); }\n.mjc-body--flush { padding: 0; } /* a table fills the panel edge to edge */\n.mjc-body > * + * { margin-top: var(--mj-space-3); } /* nothing ever touches its neighbour */\n\n.mjc-note {\n margin: 0;\n color: var(--mj-text-muted);\n font-size: var(--mj-text-xs);\n line-height: 1.55;\n}\n\n/* A note under a flush table needs its own padding and a rule above it, or it reads as a table row. */\n.mjc-note--footer {\n padding: var(--mj-space-3) var(--mj-space-4);\n border-top: 1px solid var(--mj-border-subtle);\n}\n\n/* \u2500\u2500 Hero (mockup 1) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.mjc-hero {\n display: flex;\n flex-direction: column;\n gap: var(--mj-space-4);\n padding: var(--mj-space-4) var(--mj-space-5);\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-lg);\n box-shadow: var(--mj-shadow-sm);\n}\n\n.mjc-hero__identity { display: flex; align-items: center; gap: var(--mj-space-4); min-width: 0; }\n\n.mjc-hero__avatar {\n flex: none;\n width: 52px; height: 52px;\n border-radius: var(--mj-radius-md);\n display: flex; align-items: center; justify-content: center;\n background: color-mix(in srgb, var(--mj-brand-primary) 18%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n font-size: var(--mj-text-xl, 1.375rem);\n}\n\n.mjc-hero__copy { min-width: 0; flex: 1; }\n\n.mjc-hero__title-row {\n display: flex; align-items: center; flex-wrap: wrap;\n gap: var(--mj-space-2) var(--mj-space-3);\n}\n\n.mjc-hero__title {\n margin: 0;\n font-size: var(--mj-text-lg);\n font-weight: 700;\n line-height: 1.25;\n /* Long contract descriptions must not push the chips off the card. */\n overflow-wrap: anywhere;\n}\n\n.mjc-hero__meta {\n display: flex; flex-wrap: wrap;\n gap: var(--mj-space-3);\n color: var(--mj-text-secondary);\n font-size: var(--mj-text-sm);\n margin-top: var(--mj-space-2);\n}\n\n/* auto-fit so five stats sit in a row on a wide screen and reflow on a laptop, rather than\n overflowing the card \u2014 which is what a fixed five-column grid did. */\n.mjc-hero__stats {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(8.5rem, 1fr));\n gap: var(--mj-space-3);\n}\n\n.mjc-stat {\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n padding: var(--mj-space-3);\n min-width: 0;\n}\n.mjc-stat__label {\n display: block; font-size: var(--mj-text-xs);\n text-transform: uppercase; letter-spacing: .04em;\n color: var(--mj-text-muted);\n}\n.mjc-stat__value {\n display: block; font-size: var(--mj-text-base); font-weight: 700; margin-top: 2px;\n overflow-wrap: anywhere;\n}\n.mjc-stat__sub { display: block; font-size: var(--mj-text-xs); color: var(--mj-text-muted); }\n\n/* \u2500\u2500 Chips \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.mjc-chip {\n display: inline-flex; align-items: center; gap: 4px;\n font-size: var(--mj-text-xs); font-weight: 600;\n padding: 2px 9px; border-radius: 999px;\n border: 1px solid transparent; white-space: nowrap;\n}\n.mjc-chip--ok { background: var(--mj-status-success-bg); color: var(--mj-status-success-text); border-color: var(--mj-status-success); }\n.mjc-chip--warn { background: var(--mj-status-warning-bg); color: var(--mj-status-warning-text); border-color: var(--mj-status-warning); }\n.mjc-chip--error { background: var(--mj-status-error-bg); color: var(--mj-status-error-text); border-color: var(--mj-status-error); }\n.mjc-chip--info { background: var(--mj-status-info-bg); color: var(--mj-status-info-text); border-color: var(--mj-status-info-border); }\n.mjc-chip--muted { background: var(--mj-border-subtle); color: var(--mj-text-secondary); border-color: var(--mj-border-default); }\n\n/* \u2500\u2500 Buttons \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.mjc-btn {\n display: inline-flex; align-items: center; gap: 6px;\n font-size: var(--mj-text-sm); font-weight: 600;\n padding: 6px 12px;\n border-radius: var(--mj-radius-sm);\n border: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface);\n color: var(--mj-text-primary);\n cursor: pointer;\n}\n.mjc-btn:disabled { opacity: .5; cursor: default; }\n.mjc-btn--primary { background: var(--mj-brand-primary); border-color: var(--mj-brand-primary); color: var(--mj-brand-on-primary); }\n.mjc-btn--flat { background: transparent; border-color: transparent; color: var(--mj-brand-primary); }\n.mjc-btn--sm { padding: 3px 9px; font-size: var(--mj-text-xs); }\n.mjc-btn--danger { color: var(--mj-status-error-text); border-color: transparent; background: transparent; }\n\n/* \u2500\u2500 Field grid \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.mjc-fields {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));\n gap: var(--mj-space-3) var(--mj-space-4);\n}\n.mjc-field > label {\n display: block; font-size: var(--mj-text-xs); color: var(--mj-text-muted);\n text-transform: uppercase; letter-spacing: .04em; margin-bottom: 3px;\n}\n.mjc-field .mjc-val {\n padding: 6px 9px;\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-sm);\n background: var(--mj-bg-surface);\n min-height: 31px;\n overflow-wrap: anywhere;\n}\n.mjc-field .mjc-val--ro { background: var(--mj-bg-surface-sunken); color: var(--mj-text-secondary); }\n\n/* EDIT MODE MATCHES READ MODE. These panels render bare native controls -- `<input type=\"date\">`,\n `<input type=\"number\">`, `<select>` -- because the generated datetime picker shows a time\n component for a `date` column, which is the whole reason the Dates panel exists. A bare control\n inherits none of the app's typography or chrome, so the same field visibly changed font, height\n and border the moment you pressed Edit. This mirrors `.mjc-val` above, field for field, so\n toggling edit does not move anything on screen.\n\n `font: inherit` is doing real work: form controls do NOT inherit font from their ancestor by\n default in any browser -- they fall back to a UA font -- so without it the value box and the\n input disagree even when every other property matches.\n\n THE WIDTH LIVES HERE, not on each control. The panels used to carry seven inline\n `style=\"width:100%\"` attributes; they are gone, and this rule is what replaces them. */\n.mjc-field input,\n.mjc-field select {\n width: 100%;\n box-sizing: border-box;\n font: inherit;\n color: inherit;\n padding: 6px 9px;\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-sm);\n background: var(--mj-bg-surface);\n min-height: 31px;\n}\n.mjc-field input:focus-visible,\n.mjc-field select:focus-visible { outline: 2px solid var(--mj-brand-primary); outline-offset: -1px; }\n.mjc-field input:disabled,\n.mjc-field select:disabled { background: var(--mj-bg-surface-sunken); color: var(--mj-text-secondary); }\n.mjc-hint { color: var(--mj-text-muted); font-size: var(--mj-text-xs); margin-top: 3px; }\n\n/* \u2500\u2500 Tables \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n The mockup renders modifications, documents and lineage as TABLES, not stacked cards. With three\n or more rows a table is scannable and a stack is a wall. */\n\ntable.mjc-grid { width: 100%; border-collapse: collapse; }\ntable.mjc-grid th {\n text-align: left; font-size: var(--mj-text-xs);\n text-transform: uppercase; letter-spacing: .04em;\n color: var(--mj-text-muted); font-weight: 700;\n padding: var(--mj-space-2) var(--mj-space-3);\n border-bottom: 1.5px solid var(--mj-border-default);\n}\ntable.mjc-grid td {\n padding: var(--mj-space-3);\n border-bottom: 1px solid var(--mj-border-subtle);\n vertical-align: top;\n}\ntable.mjc-grid tr:last-child td { border-bottom: 0; }\ntable.mjc-grid tbody tr:hover td { background: var(--mj-bg-surface-sunken); }\n.mjc-row--click { cursor: pointer; }\n\n.mjc-muted { color: var(--mj-text-muted); }\n.mjc-mono { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: var(--mj-text-xs); }\n\n/* \u2500\u2500 The clause pair (mockups 1 and 2) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n The standard clause and what this contract says instead, read side by side. This is the app's\n central idea rendered, so it gets real styling rather than two paragraphs. */\n\n.mjc-pair {\n display: grid; grid-template-columns: 1fr; gap: var(--mj-space-3);\n margin-top: var(--mj-space-2);\n}\n/* Side by side only when there is room \u2014 two 40ch columns on a laptop is worse than one readable one. */\n@media (min-width: 1100px) { .mjc-pair { grid-template-columns: 1fr 1fr; } }\n\n.mjc-pair__tag {\n display: block; font-size: var(--mj-text-xs); font-weight: 700;\n text-transform: uppercase; letter-spacing: .04em;\n color: var(--mj-text-muted); margin-bottom: 3px;\n}\n.mjc-pair__tag--mod { color: var(--mj-status-warning-text); }\n\n.mjc-clause {\n font-size: var(--mj-text-xs);\n color: var(--mj-text-secondary);\n background: var(--mj-bg-surface-sunken);\n border-left: 2px solid var(--mj-border-strong);\n padding: var(--mj-space-2) var(--mj-space-3);\n border-radius: 0 var(--mj-radius-sm) var(--mj-radius-sm) 0;\n margin: 0;\n /* Clause text carries its own line breaks, and 9.1 is a single 1,100-character sentence in caps \u2014\n both must wrap inside the box rather than escaping it. */\n white-space: pre-wrap;\n overflow-wrap: anywhere;\n}\n.mjc-clause--mod {\n border-left-color: var(--mj-status-warning);\n background: var(--mj-status-warning-bg);\n color: var(--mj-text-primary);\n}\n\n.mjc-toggle {\n font-size: var(--mj-text-xs); color: var(--mj-brand-primary);\n font-weight: 600; margin-top: 4px; background: none; border: 0; padding: 0; cursor: pointer;\n}\n\n/* \u2500\u2500 Callout \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.mjc-flag {\n background: var(--mj-status-warning-bg);\n border-left: 3px solid var(--mj-status-warning);\n padding: var(--mj-space-2) var(--mj-space-3);\n font-size: var(--mj-text-xs);\n color: var(--mj-status-warning-text);\n border-radius: 0 var(--mj-radius-sm) var(--mj-radius-sm) 0;\n line-height: 1.55;\n}\n\n/* \u2500\u2500 Invalid input \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n/* A required field the user has emptied. Border + ring only \u2014 no background change, because these\n are prose textareas and tinting the reading surface makes the text itself harder to read, which\n is the opposite of helpful when the point is \"write something here\". Tokens only, per the\n design-token gate. */\n.mjc-invalid {\n border-color: var(--mj-status-error) !important;\n box-shadow: 0 0 0 2px var(--mj-status-error-bg);\n outline: none;\n}\n\n/* \u2500\u2500 Filter pills (watchlist) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.mjc-pills { display: flex; flex-wrap: wrap; gap: var(--mj-space-2); align-items: center; }\n\n.mjc-pill {\n appearance: none; cursor: pointer;\n border: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface);\n color: var(--mj-text-secondary);\n border-radius: 999px;\n padding: 3px var(--mj-space-3);\n font-size: var(--mj-text-sm);\n line-height: 1.6;\n display: inline-flex; align-items: center; gap: var(--mj-space-2);\n}\n.mjc-pill:hover { border-color: var(--mj-brand-primary); color: var(--mj-text-primary); }\n.mjc-pill:disabled { opacity: .5; cursor: default; }\n.mjc-pill--active {\n background: var(--mj-status-info-bg);\n border-color: var(--mj-brand-primary);\n color: var(--mj-status-info-text);\n font-weight: 700;\n}\n.mjc-pill__count { font-variant-numeric: tabular-nums; opacity: .85; font-size: var(--mj-text-xs); }\n\n/* \u2500\u2500 Dashboard command center \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.mjc-kpis {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));\n gap: var(--mj-space-3);\n}\n.mjc-kpi {\n appearance: none;\n font: inherit;\n text-align: left;\n color: inherit;\n cursor: pointer;\n padding: var(--mj-space-3) var(--mj-space-4);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n background: var(--mj-bg-surface);\n}\n.mjc-kpi:hover { border-color: var(--mj-brand-primary); }\n.mjc-kpi:disabled { opacity: .6; cursor: default; }\n.mjc-kpi--alert .mjc-kpi__v { color: var(--mj-status-error-text); }\n.mjc-kpi__l {\n font-size: var(--mj-text-xs);\n font-weight: 700;\n text-transform: uppercase;\n letter-spacing: .04em;\n color: var(--mj-text-muted);\n}\n.mjc-kpi__v {\n font-size: var(--mj-text-xl, 1.35rem);\n font-weight: 700;\n margin: 4px 0 2px;\n font-variant-numeric: tabular-nums;\n}\n.mjc-kpi__f {\n font-size: var(--mj-text-xs);\n color: var(--mj-text-secondary);\n line-height: 1.35;\n}\n\n.mjc-dash-split {\n display: grid;\n grid-template-columns: 1.15fr .85fr;\n gap: var(--mj-space-3);\n}\n@media (max-width: 900px) { .mjc-dash-split { grid-template-columns: 1fr; } }\n\n.mjc-dash-card {\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n overflow: hidden;\n}\n.mjc-dash-card__h {\n display: flex;\n justify-content: space-between;\n gap: var(--mj-space-2);\n align-items: baseline;\n padding: var(--mj-space-3) var(--mj-space-4);\n border-bottom: 1px solid var(--mj-border-subtle);\n font-weight: 700;\n}\n.mjc-dash-card__h span {\n font-weight: 500;\n font-size: var(--mj-text-xs);\n color: var(--mj-text-muted);\n}\n\n.mjc-barlist { display: flex; flex-direction: column; gap: var(--mj-space-2); padding: var(--mj-space-3) var(--mj-space-4); }\n.mjc-barrow {\n display: grid;\n grid-template-columns: 7.5rem 1fr auto;\n gap: var(--mj-space-2);\n align-items: center;\n font-size: var(--mj-text-sm);\n}\n.mjc-track {\n height: 8px;\n background: var(--mj-bg-surface-sunken);\n border-radius: 99px;\n overflow: hidden;\n}\n.mjc-fill {\n height: 100%;\n background: var(--mj-brand-primary);\n border-radius: 99px;\n}\n.mjc-num { font-variant-numeric: tabular-nums; font-weight: 700; }\n\n.mjc-funnel {\n display: flex;\n gap: var(--mj-space-2);\n align-items: flex-end;\n height: 10rem;\n padding: var(--mj-space-3) var(--mj-space-4);\n}\n.mjc-funnel__col {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 6px;\n}\n.mjc-funnel__bar {\n width: 100%;\n min-height: 8px;\n border-radius: 8px 8px 2px 2px;\n background: var(--mj-brand-primary);\n}\n.mjc-funnel__n { font-weight: 700; }\n.mjc-funnel__lab {\n font-size: var(--mj-text-xs);\n color: var(--mj-text-muted);\n text-align: center;\n}\n\n.mjc-buckets {\n display: grid;\n grid-template-columns: repeat(4, 1fr);\n gap: var(--mj-space-2);\n padding: var(--mj-space-3) var(--mj-space-4);\n}\n@media (max-width: 700px) { .mjc-buckets { grid-template-columns: 1fr 1fr; } }\n.mjc-bucket {\n background: var(--mj-bg-page);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n padding: var(--mj-space-3);\n}\n\n.mjc-viewer-host {\n min-height: 420px;\n height: 480px;\n display: flex;\n flex-direction: column;\n}\n.mjc-viewer-host mj-entity-viewer {\n display: flex;\n flex-direction: column;\n flex: 1 1 auto;\n min-height: 350px;\n width: 100%;\n}\n\n/* \u2500\u2500 Empty state \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n A sentence in a bordered box, never a bare line of text in whitespace. */\n\n.mjc-empty {\n display: flex; align-items: center; gap: var(--mj-space-2); justify-content: center;\n padding: var(--mj-space-6);\n color: var(--mj-text-muted);\n font-size: var(--mj-text-sm);\n background: var(--mj-bg-surface-sunken);\n border: 1px dashed var(--mj-border-strong);\n border-radius: var(--mj-radius-md);\n text-align: center;\n}\n", "\n .mjc-hero {\n display: flex; flex-direction: column; gap: var(--mj-space-4);\n padding: 20px 24px; margin-bottom: var(--mj-space-4);\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-xl, 16px);\n box-shadow: var(--mj-shadow-md, 0 4px 16px rgba(0, 0, 0, .08));\n position: relative; overflow: hidden;\n }\n .mjc-hero::before {\n content: ''; position: absolute; top: 0; left: 0; right: 0; height: 3.5px;\n background: linear-gradient(90deg, #38bdf8 0%, #6366f1 50%, #10b981 100%);\n }\n .mjc-hero__identity { display: flex; align-items: center; gap: var(--mj-space-4); min-width: 0; }\n .mjc-hero__avatar {\n flex: none; width: 60px; height: 60px; border-radius: var(--mj-radius-lg, 14px);\n position: relative; display: flex; align-items: center; justify-content: center;\n background: linear-gradient(135deg, color-mix(in srgb, var(--mj-brand-primary) 30%, var(--mj-bg-surface)) 0%, color-mix(in srgb, var(--mj-brand-accent, #6366f1) 25%, var(--mj-bg-surface)) 100%);\n color: var(--mj-brand-primary); font-size: 1.35rem;\n box-shadow: 0 4px 14px color-mix(in srgb, var(--mj-brand-primary) 25%, transparent);\n border: 2px solid color-mix(in srgb, var(--mj-brand-primary) 35%, transparent);\n }\n .mjc-hero__presence {\n position: absolute; bottom: -2px; right: -2px; width: 13px; height: 13px;\n border-radius: 50%; border: 2.5px solid var(--mj-bg-surface-card);\n background: var(--mj-text-muted, #94a3b8);\n }\n .mjc-hero__presence[data-tone='success'] { background: var(--mj-status-success, #10b981); }\n .mjc-hero__presence[data-tone='warning'] { background: var(--mj-status-warning, #f59e0b); }\n .mjc-hero__copy { min-width: 0; flex: 1; }\n .mjc-hero__title {\n margin: 0; font-size: var(--mj-text-lg, 18px); font-weight: 800;\n letter-spacing: -.02em; line-height: 1.25; color: var(--mj-text-primary);\n overflow-wrap: anywhere;\n }\n .mjc-hero__aka { margin-top: 2px; font-size: var(--mj-text-xs); color: var(--mj-text-muted); }\n .mjc-hero__badges {\n display: flex; align-items: center; flex-wrap: wrap;\n gap: var(--mj-space-2); margin-top: var(--mj-space-2);\n }\n .mjc-hero__entity-chip {\n display: inline-flex; align-items: center; gap: 4px; padding: 2px 8px;\n border-radius: var(--mj-radius-sm);\n background: var(--mj-status-info-bg); color: var(--mj-brand-primary);\n font-size: var(--mj-text-xs); font-weight: 650;\n }\n .mjc-hero__toggle {\n display: inline-flex; align-items: center; justify-content: center;\n flex: none; width: 32px; height: 32px; margin-left: auto; padding: 0;\n border: 1px solid var(--mj-border-default); border-radius: var(--mj-radius-md, 8px);\n background: var(--mj-bg-surface-sunken, rgba(255,255,255,.04));\n color: var(--mj-text-secondary); cursor: pointer; font-size: 12px;\n }\n .mjc-hero__toggle:hover {\n background: var(--mj-bg-surface-hover, rgba(255,255,255,.08));\n color: var(--mj-text-primary); border-color: var(--mj-brand-primary);\n }\n .mjc-hero__summary {\n display: grid; grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));\n gap: var(--mj-space-3); padding-top: var(--mj-space-4);\n border-top: 1px solid var(--mj-border-default);\n }\n .mjc-hero__stat { display: flex; flex-direction: column; gap: 3px; min-width: 0; }\n .mjc-hero__stat-label {\n font-size: var(--mj-text-xs); font-weight: 700; letter-spacing: .04em;\n text-transform: uppercase; color: var(--mj-text-muted);\n }\n .mjc-hero__stat-val {\n font-size: 15px; font-weight: 650; color: var(--mj-text-primary);\n overflow: hidden; text-overflow: ellipsis; white-space: nowrap;\n }\n button.mjc-hero__stat-val, .mjc-hero__stat-val.is-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 button.mjc-hero__stat-val:hover { text-decoration: underline; }\n .mjc-hero__next {\n display: flex; flex-wrap: wrap; align-items: baseline; gap: 8px 14px;\n padding: var(--mj-space-3) var(--mj-space-4);\n background: var(--mj-bg-page); border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n }\n .mjc-hero__next-val { font-weight: 700; font-size: 15px; }\n .mjc-hero__edit {\n display: flex; flex-direction: column; gap: var(--mj-space-3);\n padding-top: var(--mj-space-3); border-top: 1px solid var(--mj-border-subtle, var(--mj-border-default));\n }\n .mjc-hero__field { min-width: 0; }\n .mjc-hero__field .mj-forms-field {\n display: flex; flex-direction: column; align-items: stretch; gap: 4px; padding: 0;\n }\n .mjc-hero__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 .mjc-hero--collapsed { padding: 12px 20px; gap: 0; margin-bottom: var(--mj-space-3); }\n .mjc-hero--collapsed .mjc-hero__avatar { width: 42px; height: 42px; border-radius: var(--mj-radius-md, 10px); font-size: 1.05rem; }\n .mjc-hero--collapsed .mjc-hero__title { font-size: 1.15rem; }\n @media (max-width: 720px) {\n .mjc-hero__identity { align-items: flex-start; }\n .mjc-hero__summary { grid-template-columns: repeat(2, minmax(0, 1fr)); }\n }\n "] }]
|
|
604
863
|
}], null, null); })();
|
|
605
|
-
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MJCContractHeroPanel, { className: "MJCContractHeroPanel", filePath: "lib/form-panels/contract.panels.ts", lineNumber:
|
|
864
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MJCContractHeroPanel, { className: "MJCContractHeroPanel", filePath: "lib/form-panels/contract.panels.ts", lineNumber: 303 }); })();
|
|
606
865
|
/* ────────────────────────────────────────────────────────────────────────────
|
|
607
866
|
* 2 · Renewal terms — a real rail section
|
|
608
867
|
* ──────────────────────────────────────────────────────────────────────────── */
|
|
609
868
|
let MJCContractRenewalPanel = class MJCContractRenewalPanel extends BaseFormPanel {
|
|
869
|
+
/**
|
|
870
|
+
* A day count, where ZERO IS A VALUE (issue #28 item 21).
|
|
871
|
+
*
|
|
872
|
+
* `Record.X ? … : '—'` conflates ZERO with ABSENT: a recorded `0` rendered as the same em dash as
|
|
873
|
+
* a blank, so the panel reported holding no figure about a figure that says "no notice is
|
|
874
|
+
* required" — which somebody negotiated. `== null` is the whole fix, and it is deliberately `==`
|
|
875
|
+
* rather than `===` so `undefined` is caught too.
|
|
876
|
+
*/
|
|
877
|
+
Days(v) {
|
|
878
|
+
return v == null ? '—' : `${v} days`;
|
|
879
|
+
}
|
|
880
|
+
/** Same rule for the percentage: `0%` is a negotiated cap, not a missing value. */
|
|
881
|
+
Percent(v) {
|
|
882
|
+
return v == null ? '—' : `${v}%`;
|
|
883
|
+
}
|
|
884
|
+
/**
|
|
885
|
+
* Whether this agreement genuinely states no renewal terms.
|
|
886
|
+
*
|
|
887
|
+
* AUTO-RENEWS IS ONE OF THE TERMS, and leaving it out of the condition is why the empty state
|
|
888
|
+
* used to contradict the screen: `AutoRenew = Yes` with blank day counts showed "No renewal terms
|
|
889
|
+
* recorded" directly beneath a field reading Yes. Auto-renewal is the most consequential renewal
|
|
890
|
+
* term there is, so the panel is only empty when it is No AND all three numbers are absent.
|
|
891
|
+
*/
|
|
892
|
+
get NoTermsRecorded() {
|
|
893
|
+
return !this.Record?.AutoRenew &&
|
|
894
|
+
this.Record?.RenewalNoticeDays == null &&
|
|
895
|
+
this.Record?.CancellationWindowDays == null &&
|
|
896
|
+
this.Record?.AnnualIncreasePercent == null;
|
|
897
|
+
}
|
|
610
898
|
/**
|
|
611
899
|
* Write a field through the typed entity. Named `Set` rather than bound with two-way `[(ngModel)]`
|
|
612
900
|
* so the write goes through one place — a two-way binding on `Record.X` works but gives no hook for
|
|
@@ -619,7 +907,7 @@ let MJCContractRenewalPanel = class MJCContractRenewalPanel extends BaseFormPane
|
|
|
619
907
|
get NoticeDeadline() { return this.Record?.RenewalNoticeDeadline ?? null; }
|
|
620
908
|
get InCancellationWindow() { return this.Record?.IsInCancellationWindow === true; }
|
|
621
909
|
static ɵfac = /*@__PURE__*/ (() => { let ɵMJCContractRenewalPanel_BaseFactory; return function MJCContractRenewalPanel_Factory(__ngFactoryType__) { return (ɵMJCContractRenewalPanel_BaseFactory || (ɵMJCContractRenewalPanel_BaseFactory = i0.ɵɵgetInheritedFactory(MJCContractRenewalPanel)))(__ngFactoryType__ || MJCContractRenewalPanel); }; })();
|
|
622
|
-
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: MJCContractRenewalPanel, selectors: [["mjc-contract-renewal-panel"]], features: [i0.ɵɵInheritDefinitionFeature], decls:
|
|
910
|
+
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: MJCContractRenewalPanel, selectors: [["mjc-contract-renewal-panel"]], features: [i0.ɵɵInheritDefinitionFeature], decls: 32, vars: 9, consts: [["SectionKey", "renewal", "SectionName", "Renewal terms", "Icon", "fa-solid fa-calendar-days", 3, "Form", "FormContext"], [1, "mjc-body"], [1, "mjc-chip", "mjc-chip--muted"], [1, "mjc-fields"], [1, "mjc-field"], ["aria-label", "Does this agreement auto-renew?", 3, "ngModel"], [1, "mjc-val"], ["type", "number", "min", "0", "aria-label", "Renewal notice days", 3, "ngModel"], [1, "mjc-hint"], ["type", "number", "min", "0", "aria-label", "Cancellation window days", 3, "ngModel"], ["type", "number", "min", "0", "step", "0.01", "aria-label", "Annual increase percent", 3, "ngModel"], [1, "mjc-empty"], ["aria-label", "Does this agreement auto-renew?", 3, "ngModelChange", "ngModel"], [3, "ngValue"], ["type", "number", "min", "0", "aria-label", "Renewal notice days", 3, "ngModelChange", "ngModel"], ["type", "number", "min", "0", "aria-label", "Cancellation window days", 3, "ngModelChange", "ngModel"], ["type", "number", "min", "0", "step", "0.01", "aria-label", "Annual increase percent", 3, "ngModelChange", "ngModel"]], template: function MJCContractRenewalPanel_Template(rf, ctx) { if (rf & 1) {
|
|
623
911
|
i0.ɵɵelementStart(0, "mj-collapsible-panel", 0)(1, "div", 1)(2, "span", 2);
|
|
624
912
|
i0.ɵɵtext(3, "as stated in the agreement");
|
|
625
913
|
i0.ɵɵelementEnd();
|
|
@@ -627,49 +915,49 @@ let MJCContractRenewalPanel = class MJCContractRenewalPanel extends BaseFormPane
|
|
|
627
915
|
i0.ɵɵtext(7, "Auto-renews");
|
|
628
916
|
i0.ɵɵelementEnd();
|
|
629
917
|
i0.ɵɵconditionalCreate(8, MJCContractRenewalPanel_Conditional_8_Template, 5, 3, "select", 5)(9, MJCContractRenewalPanel_Conditional_9_Template, 2, 1, "div", 6);
|
|
630
|
-
i0.ɵɵconditionalCreate(10, MJCContractRenewalPanel_Conditional_10_Template, 2, 0, "div", 7);
|
|
631
918
|
i0.ɵɵelementEnd();
|
|
632
|
-
i0.ɵɵelementStart(
|
|
633
|
-
i0.ɵɵtext(
|
|
919
|
+
i0.ɵɵelementStart(10, "div", 4)(11, "label");
|
|
920
|
+
i0.ɵɵtext(12, "Renewal notice (days)");
|
|
634
921
|
i0.ɵɵelementEnd();
|
|
635
|
-
i0.ɵɵconditionalCreate(
|
|
636
|
-
i0.ɵɵ
|
|
922
|
+
i0.ɵɵconditionalCreate(13, MJCContractRenewalPanel_Conditional_13_Template, 1, 1, "input", 7)(14, MJCContractRenewalPanel_Conditional_14_Template, 2, 1, "div", 6);
|
|
923
|
+
i0.ɵɵelementStart(15, "div", 8);
|
|
924
|
+
i0.ɵɵtext(16, " Written notice we must give the customer before a renewal price change. ");
|
|
637
925
|
i0.ɵɵelementEnd();
|
|
638
|
-
i0.ɵɵ
|
|
639
|
-
i0.ɵɵtext(19, "Notice to cancel (days)");
|
|
926
|
+
i0.ɵɵconditionalCreate(17, MJCContractRenewalPanel_Conditional_17_Template, 3, 4, "div", 8);
|
|
640
927
|
i0.ɵɵelementEnd();
|
|
641
|
-
i0.ɵɵ
|
|
642
|
-
i0.ɵɵ
|
|
928
|
+
i0.ɵɵelementStart(18, "div", 4)(19, "label");
|
|
929
|
+
i0.ɵɵtext(20, "Notice to cancel (days)");
|
|
643
930
|
i0.ɵɵelementEnd();
|
|
644
|
-
i0.ɵɵ
|
|
645
|
-
i0.ɵɵ
|
|
931
|
+
i0.ɵɵconditionalCreate(21, MJCContractRenewalPanel_Conditional_21_Template, 1, 1, "input", 9)(22, MJCContractRenewalPanel_Conditional_22_Template, 2, 1, "div", 6);
|
|
932
|
+
i0.ɵɵelementStart(23, "div", 8);
|
|
933
|
+
i0.ɵɵtext(24, "Notice the customer must give us to cancel.");
|
|
646
934
|
i0.ɵɵelementEnd();
|
|
647
|
-
i0.ɵɵconditionalCreate(
|
|
648
|
-
i0.ɵɵelementEnd()();
|
|
649
|
-
i0.ɵɵelementStart(28, "p", 11);
|
|
650
|
-
i0.ɵɵtext(29, " These record what the signed paper says. The subscription in orders holds the operational setting and may legitimately differ \u2014 a mismatch is a finding, not a bug. ");
|
|
935
|
+
i0.ɵɵconditionalCreate(25, MJCContractRenewalPanel_Conditional_25_Template, 2, 0, "div", 8);
|
|
651
936
|
i0.ɵɵelementEnd();
|
|
652
|
-
i0.ɵɵ
|
|
937
|
+
i0.ɵɵelementStart(26, "div", 4)(27, "label");
|
|
938
|
+
i0.ɵɵtext(28, "Annual increase (%)");
|
|
939
|
+
i0.ɵɵelementEnd();
|
|
940
|
+
i0.ɵɵconditionalCreate(29, MJCContractRenewalPanel_Conditional_29_Template, 1, 1, "input", 10)(30, MJCContractRenewalPanel_Conditional_30_Template, 2, 1, "div", 6);
|
|
941
|
+
i0.ɵɵelementEnd()();
|
|
942
|
+
i0.ɵɵconditionalCreate(31, MJCContractRenewalPanel_Conditional_31_Template, 2, 0, "div", 11);
|
|
653
943
|
i0.ɵɵelementEnd()();
|
|
654
944
|
} if (rf & 2) {
|
|
655
945
|
i0.ɵɵproperty("Form", ctx.FormComponent)("FormContext", ctx.FormContext);
|
|
656
946
|
i0.ɵɵadvance(8);
|
|
657
947
|
i0.ɵɵconditional(ctx.EditMode ? 8 : 9);
|
|
658
|
-
i0.ɵɵadvance(
|
|
659
|
-
i0.ɵɵconditional(
|
|
948
|
+
i0.ɵɵadvance(5);
|
|
949
|
+
i0.ɵɵconditional(ctx.EditMode ? 13 : 14);
|
|
660
950
|
i0.ɵɵadvance(4);
|
|
661
|
-
i0.ɵɵconditional(ctx.
|
|
662
|
-
i0.ɵɵadvance(2);
|
|
663
|
-
i0.ɵɵconditional(ctx.NoticeDeadline ? 16 : -1);
|
|
951
|
+
i0.ɵɵconditional(ctx.NoticeDeadline ? 17 : -1);
|
|
664
952
|
i0.ɵɵadvance(4);
|
|
665
|
-
i0.ɵɵconditional(ctx.EditMode ?
|
|
666
|
-
i0.ɵɵadvance(2);
|
|
667
|
-
i0.ɵɵconditional(ctx.InCancellationWindow ? 22 : -1);
|
|
953
|
+
i0.ɵɵconditional(ctx.EditMode ? 21 : 22);
|
|
668
954
|
i0.ɵɵadvance(4);
|
|
669
|
-
i0.ɵɵconditional(ctx.
|
|
955
|
+
i0.ɵɵconditional(ctx.InCancellationWindow ? 25 : -1);
|
|
670
956
|
i0.ɵɵadvance(4);
|
|
671
|
-
i0.ɵɵconditional(
|
|
672
|
-
|
|
957
|
+
i0.ɵɵconditional(ctx.EditMode ? 29 : 30);
|
|
958
|
+
i0.ɵɵadvance(2);
|
|
959
|
+
i0.ɵɵconditional(ctx.NoTermsRecorded ? 31 : -1);
|
|
960
|
+
} }, dependencies: [CommonModule, FormsModule, i3.NgSelectOption, i3.ɵNgSelectMultipleOption, i3.DefaultValueAccessor, i3.NumberValueAccessor, i3.SelectControlValueAccessor, i3.NgControlStatus, i3.MinValidator, i3.NgModel, BaseFormsModule, i1.MjCollapsiblePanelComponent, i2.DatePipe], encapsulation: 2 });
|
|
673
961
|
};
|
|
674
962
|
MJCContractRenewalPanel = __decorate([
|
|
675
963
|
RegisterClassEx(BaseFormPanel, {
|
|
@@ -739,18 +1027,24 @@ export { MJCContractRenewalPanel };
|
|
|
739
1027
|
} @else {
|
|
740
1028
|
<div class="mjc-val">{{ Record.AutoRenew ? 'Yes' : 'No' }}</div>
|
|
741
1029
|
}
|
|
742
|
-
@if (!Record.AutoRenew) {
|
|
743
|
-
<div class="mjc-hint">someone must act for this to continue</div>
|
|
744
|
-
}
|
|
745
1030
|
</div>
|
|
746
1031
|
<div class="mjc-field">
|
|
747
|
-
<label>Renewal notice
|
|
1032
|
+
<label>Renewal notice (days)</label>
|
|
748
1033
|
@if (EditMode) {
|
|
749
|
-
<input type="number" min="0"
|
|
1034
|
+
<input type="number" min="0" [ngModel]="Record.RenewalNoticeDays"
|
|
750
1035
|
(ngModelChange)="Set('RenewalNoticeDays', $event)" aria-label="Renewal notice days" />
|
|
751
1036
|
} @else {
|
|
752
|
-
<div class="mjc-val">{{ Record.RenewalNoticeDays
|
|
1037
|
+
<div class="mjc-val">{{ Days(Record.RenewalNoticeDays) }}</div>
|
|
753
1038
|
}
|
|
1039
|
+
<!--
|
|
1040
|
+
WHICH DIRECTION THE NOTICE RUNS IS THE WHOLE POINT (#28 item 6). This field
|
|
1041
|
+
and CancellationWindowDays below are both "a number of days of notice",
|
|
1042
|
+
and the old labels left the reader to work out whose notice each one was.
|
|
1043
|
+
One is what we owe them; the other is what they owe us.
|
|
1044
|
+
-->
|
|
1045
|
+
<div class="mjc-hint">
|
|
1046
|
+
Written notice we must give the customer before a renewal price change.
|
|
1047
|
+
</div>
|
|
754
1048
|
@if (NoticeDeadline) {
|
|
755
1049
|
<div class="mjc-hint">deadline: {{ NoticeDeadline | date: 'd MMM y' }}</div>
|
|
756
1050
|
}
|
|
@@ -758,41 +1052,35 @@ export { MJCContractRenewalPanel };
|
|
|
758
1052
|
<div class="mjc-field">
|
|
759
1053
|
<label>Notice to cancel (days)</label>
|
|
760
1054
|
@if (EditMode) {
|
|
761
|
-
<input type="number" min="0"
|
|
1055
|
+
<input type="number" min="0" [ngModel]="Record.CancellationWindowDays"
|
|
762
1056
|
(ngModelChange)="Set('CancellationWindowDays', $event)" aria-label="Cancellation window days" />
|
|
763
1057
|
} @else {
|
|
764
|
-
<div class="mjc-val">{{ Record.CancellationWindowDays
|
|
1058
|
+
<div class="mjc-val">{{ Days(Record.CancellationWindowDays) }}</div>
|
|
765
1059
|
}
|
|
1060
|
+
<div class="mjc-hint">Notice the customer must give us to cancel.</div>
|
|
766
1061
|
@if (InCancellationWindow) { <div class="mjc-hint">the window is open now</div> }
|
|
767
1062
|
</div>
|
|
768
1063
|
<div class="mjc-field">
|
|
769
1064
|
<label>Annual increase (%)</label>
|
|
770
1065
|
@if (EditMode) {
|
|
771
|
-
<input type="number" min="0" step="0.01"
|
|
1066
|
+
<input type="number" min="0" step="0.01" [ngModel]="Record.AnnualIncreasePercent"
|
|
772
1067
|
(ngModelChange)="Set('AnnualIncreasePercent', $event)" aria-label="Annual increase percent" />
|
|
773
1068
|
} @else {
|
|
774
|
-
<div class="mjc-val">{{ Record.AnnualIncreasePercent
|
|
1069
|
+
<div class="mjc-val">{{ Percent(Record.AnnualIncreasePercent) }}</div>
|
|
775
1070
|
}
|
|
776
1071
|
</div>
|
|
777
1072
|
</div>
|
|
778
1073
|
|
|
779
|
-
<p class="mjc-note">
|
|
780
|
-
These record what the signed paper says. The subscription in orders holds the operational
|
|
781
|
-
setting and may legitimately differ — a mismatch is a finding, not a bug.
|
|
782
|
-
</p>
|
|
783
1074
|
|
|
784
|
-
@if (
|
|
785
|
-
<div class="mjc-empty">
|
|
786
|
-
No renewal terms recorded. If the agreement states any, recording them is what puts this
|
|
787
|
-
contract on the renewals watchlist.
|
|
788
|
-
</div>
|
|
1075
|
+
@if (NoTermsRecorded) {
|
|
1076
|
+
<div class="mjc-empty">No renewal terms recorded.</div>
|
|
789
1077
|
}
|
|
790
1078
|
</div>
|
|
791
1079
|
</mj-collapsible-panel>
|
|
792
1080
|
`,
|
|
793
1081
|
}]
|
|
794
1082
|
}], null, null); })();
|
|
795
|
-
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MJCContractRenewalPanel, { className: "MJCContractRenewalPanel", filePath: "lib/form-panels/contract.panels.ts", lineNumber:
|
|
1083
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MJCContractRenewalPanel, { className: "MJCContractRenewalPanel", filePath: "lib/form-panels/contract.panels.ts", lineNumber: 625 }); })();
|
|
796
1084
|
/* ────────────────────────────────────────────────────────────────────────────
|
|
797
1085
|
* 2b · Dates — its own rail section, replacing the generated `datesAndTerms`
|
|
798
1086
|
* ──────────────────────────────────────────────────────────────────────────── */
|
|
@@ -819,63 +1107,41 @@ let MJCContractDatesPanel = class MJCContractDatesPanel extends BaseFormPanel {
|
|
|
819
1107
|
SetDate(field, value) {
|
|
820
1108
|
this.Record[field] = value ? new Date(value + 'T00:00:00Z') : null;
|
|
821
1109
|
}
|
|
822
|
-
get EndsInText() {
|
|
823
|
-
const d = this.Record?.DaysToEnd ?? null;
|
|
824
|
-
if (d === null)
|
|
825
|
-
return '';
|
|
826
|
-
if (d < 0)
|
|
827
|
-
return `ended ${Math.abs(d)} days ago`;
|
|
828
|
-
if (d === 0)
|
|
829
|
-
return 'ends today';
|
|
830
|
-
return d < 60 ? `in ${d} days` : `in ${Math.round(d / 30)} months`;
|
|
831
|
-
}
|
|
832
1110
|
static ɵfac = /*@__PURE__*/ (() => { let ɵMJCContractDatesPanel_BaseFactory; return function MJCContractDatesPanel_Factory(__ngFactoryType__) { return (ɵMJCContractDatesPanel_BaseFactory || (ɵMJCContractDatesPanel_BaseFactory = i0.ɵɵgetInheritedFactory(MJCContractDatesPanel)))(__ngFactoryType__ || MJCContractDatesPanel); }; })();
|
|
833
|
-
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: MJCContractDatesPanel, selectors: [["mjc-contract-dates-panel"]], features: [i0.ɵɵInheritDefinitionFeature], decls:
|
|
1111
|
+
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: MJCContractDatesPanel, selectors: [["mjc-contract-dates-panel"]], features: [i0.ɵɵInheritDefinitionFeature], decls: 25, vars: 6, consts: [["SectionKey", "dates", "SectionName", "Dates", "Icon", "fa-solid fa-calendar", 3, "Form", "FormContext"], [1, "mjc-body"], [1, "mjc-fields"], [1, "mjc-field"], ["type", "date", "aria-label", "Executed date", 3, "ngModel"], [1, "mjc-val"], ["type", "date", "aria-label", "Effective date", 3, "ngModel"], ["type", "date", "aria-label", "End date", 3, "ngModel"], ["type", "date", "aria-label", "Terminated date", 3, "ngModel"], [1, "mjc-val", 3, "mjc-val--ro"], [1, "mjc-hint"], ["type", "date", "aria-label", "Executed date", 3, "ngModelChange", "ngModel"], ["type", "date", "aria-label", "Effective date", 3, "ngModelChange", "ngModel"], ["type", "date", "aria-label", "End date", 3, "ngModelChange", "ngModel"], ["type", "date", "aria-label", "Terminated date", 3, "ngModelChange", "ngModel"]], template: function MJCContractDatesPanel_Template(rf, ctx) { if (rf & 1) {
|
|
834
1112
|
i0.ɵɵelementStart(0, "mj-collapsible-panel", 0)(1, "div", 1)(2, "div", 2)(3, "div", 3)(4, "label");
|
|
835
1113
|
i0.ɵɵtext(5, "Executed date");
|
|
836
1114
|
i0.ɵɵelementEnd();
|
|
837
1115
|
i0.ɵɵconditionalCreate(6, MJCContractDatesPanel_Conditional_6_Template, 1, 1, "input", 4)(7, MJCContractDatesPanel_Conditional_7_Template, 3, 4, "div", 5);
|
|
838
|
-
i0.ɵɵelementStart(8, "div", 6);
|
|
839
|
-
i0.ɵɵtext(9, "may precede the effective date \u2014 that is normal, not an anomaly");
|
|
840
|
-
i0.ɵɵelementEnd()();
|
|
841
|
-
i0.ɵɵelementStart(10, "div", 3)(11, "label");
|
|
842
|
-
i0.ɵɵtext(12, "Effective date");
|
|
843
1116
|
i0.ɵɵelementEnd();
|
|
844
|
-
i0.ɵɵ
|
|
1117
|
+
i0.ɵɵelementStart(8, "div", 3)(9, "label");
|
|
1118
|
+
i0.ɵɵtext(10, "Effective date");
|
|
845
1119
|
i0.ɵɵelementEnd();
|
|
846
|
-
i0.ɵɵ
|
|
847
|
-
i0.ɵɵtext(17, "End date");
|
|
1120
|
+
i0.ɵɵconditionalCreate(11, MJCContractDatesPanel_Conditional_11_Template, 1, 1, "input", 6)(12, MJCContractDatesPanel_Conditional_12_Template, 3, 4, "div", 5);
|
|
848
1121
|
i0.ɵɵelementEnd();
|
|
849
|
-
i0.ɵɵ
|
|
850
|
-
i0.ɵɵ
|
|
1122
|
+
i0.ɵɵelementStart(13, "div", 3)(14, "label");
|
|
1123
|
+
i0.ɵɵtext(15, "End date");
|
|
851
1124
|
i0.ɵɵelementEnd();
|
|
852
|
-
i0.ɵɵ
|
|
853
|
-
i0.ɵɵtext(23, "Terminated date");
|
|
1125
|
+
i0.ɵɵconditionalCreate(16, MJCContractDatesPanel_Conditional_16_Template, 1, 1, "input", 7)(17, MJCContractDatesPanel_Conditional_17_Template, 3, 4, "div", 5);
|
|
854
1126
|
i0.ɵɵelementEnd();
|
|
855
|
-
i0.ɵɵ
|
|
856
|
-
i0.ɵɵ
|
|
857
|
-
i0.ɵɵtext(27, " a fact about what happened \u2014 set it and the contract reads Terminated regardless of its term ");
|
|
858
|
-
i0.ɵɵelementEnd()()();
|
|
859
|
-
i0.ɵɵelementStart(28, "p", 11);
|
|
860
|
-
i0.ɵɵtext(29, " The lifecycle is ");
|
|
861
|
-
i0.ɵɵelementStart(30, "strong");
|
|
862
|
-
i0.ɵɵtext(31, "derived");
|
|
1127
|
+
i0.ɵɵelementStart(18, "div", 3)(19, "label");
|
|
1128
|
+
i0.ɵɵtext(20, "Terminated date");
|
|
863
1129
|
i0.ɵɵelementEnd();
|
|
864
|
-
i0.ɵɵ
|
|
865
|
-
i0.ɵɵ
|
|
1130
|
+
i0.ɵɵconditionalCreate(21, MJCContractDatesPanel_Conditional_21_Template, 1, 1, "input", 8)(22, MJCContractDatesPanel_Conditional_22_Template, 3, 6, "div", 9);
|
|
1131
|
+
i0.ɵɵelementStart(23, "div", 10);
|
|
1132
|
+
i0.ɵɵtext(24, "Setting this marks the contract Terminated from this date.");
|
|
1133
|
+
i0.ɵɵelementEnd()()()()();
|
|
866
1134
|
} if (rf & 2) {
|
|
867
1135
|
i0.ɵɵproperty("Form", ctx.FormComponent)("FormContext", ctx.FormContext);
|
|
868
1136
|
i0.ɵɵadvance(6);
|
|
869
1137
|
i0.ɵɵconditional(ctx.EditMode ? 6 : 7);
|
|
870
|
-
i0.ɵɵadvance(7);
|
|
871
|
-
i0.ɵɵconditional(ctx.EditMode ? 13 : 14);
|
|
872
1138
|
i0.ɵɵadvance(5);
|
|
873
|
-
i0.ɵɵconditional(ctx.EditMode ?
|
|
874
|
-
i0.ɵɵadvance(
|
|
875
|
-
i0.ɵɵconditional(ctx.
|
|
876
|
-
i0.ɵɵadvance(
|
|
877
|
-
i0.ɵɵconditional(ctx.EditMode ?
|
|
878
|
-
} }, dependencies: [CommonModule, FormsModule,
|
|
1139
|
+
i0.ɵɵconditional(ctx.EditMode ? 11 : 12);
|
|
1140
|
+
i0.ɵɵadvance(5);
|
|
1141
|
+
i0.ɵɵconditional(ctx.EditMode ? 16 : 17);
|
|
1142
|
+
i0.ɵɵadvance(5);
|
|
1143
|
+
i0.ɵɵconditional(ctx.EditMode ? 21 : 22);
|
|
1144
|
+
} }, dependencies: [CommonModule, FormsModule, i3.DefaultValueAccessor, i3.NgControlStatus, i3.NgModel, BaseFormsModule, i1.MjCollapsiblePanelComponent, i2.DatePipe], encapsulation: 2 });
|
|
879
1145
|
};
|
|
880
1146
|
MJCContractDatesPanel = __decorate([
|
|
881
1147
|
RegisterClassEx(BaseFormPanel, {
|
|
@@ -927,17 +1193,16 @@ export { MJCContractDatesPanel };
|
|
|
927
1193
|
<div class="mjc-field">
|
|
928
1194
|
<label>Executed date</label>
|
|
929
1195
|
@if (EditMode) {
|
|
930
|
-
<input type="date"
|
|
1196
|
+
<input type="date" [ngModel]="AsInput(Record.ExecutedDate)"
|
|
931
1197
|
(ngModelChange)="SetDate('ExecutedDate', $event)" aria-label="Executed date" />
|
|
932
1198
|
} @else {
|
|
933
1199
|
<div class="mjc-val">{{ (Record.ExecutedDate | date: 'd MMM y') || '—' }}</div>
|
|
934
1200
|
}
|
|
935
|
-
<div class="mjc-hint">may precede the effective date — that is normal, not an anomaly</div>
|
|
936
1201
|
</div>
|
|
937
1202
|
<div class="mjc-field">
|
|
938
1203
|
<label>Effective date</label>
|
|
939
1204
|
@if (EditMode) {
|
|
940
|
-
<input type="date"
|
|
1205
|
+
<input type="date" [ngModel]="AsInput(Record.EffectiveDate)"
|
|
941
1206
|
(ngModelChange)="SetDate('EffectiveDate', $event)" aria-label="Effective date" />
|
|
942
1207
|
} @else {
|
|
943
1208
|
<div class="mjc-val">{{ (Record.EffectiveDate | date: 'd MMM y') || '—' }}</div>
|
|
@@ -946,43 +1211,35 @@ export { MJCContractDatesPanel };
|
|
|
946
1211
|
<div class="mjc-field">
|
|
947
1212
|
<label>End date</label>
|
|
948
1213
|
@if (EditMode) {
|
|
949
|
-
<input type="date"
|
|
1214
|
+
<input type="date" [ngModel]="AsInput(Record.EndDate)"
|
|
950
1215
|
(ngModelChange)="SetDate('EndDate', $event)" aria-label="End date" />
|
|
951
1216
|
} @else {
|
|
952
1217
|
<div class="mjc-val">{{ (Record.EndDate | date: 'd MMM y') || '—' }}</div>
|
|
953
1218
|
}
|
|
954
|
-
@if (Record.DaysToEnd !== null) { <div class="mjc-hint">{{ EndsInText }}</div> }
|
|
955
1219
|
</div>
|
|
956
1220
|
<div class="mjc-field">
|
|
957
1221
|
<label>Terminated date</label>
|
|
958
1222
|
@if (EditMode) {
|
|
959
|
-
<input type="date"
|
|
1223
|
+
<input type="date" [ngModel]="AsInput(Record.TerminatedDate)"
|
|
960
1224
|
(ngModelChange)="SetDate('TerminatedDate', $event)" aria-label="Terminated date" />
|
|
961
1225
|
} @else {
|
|
962
1226
|
<div class="mjc-val" [class.mjc-val--ro]="!Record.TerminatedDate">{{ (Record.TerminatedDate | date: 'd MMM y') || '—' }}</div>
|
|
963
1227
|
}
|
|
964
|
-
<div class="mjc-hint">
|
|
965
|
-
a fact about what happened — set it and the contract reads Terminated regardless of its term
|
|
966
|
-
</div>
|
|
1228
|
+
<div class="mjc-hint">Setting this marks the contract Terminated from this date.</div>
|
|
967
1229
|
</div>
|
|
968
1230
|
</div>
|
|
969
1231
|
|
|
970
|
-
<p class="mjc-note">
|
|
971
|
-
The lifecycle is <strong>derived</strong> from these four dates and the two lineage links, not
|
|
972
|
-
stored — so a state can never disagree with the dates it came from.
|
|
973
|
-
</p>
|
|
974
1232
|
</div>
|
|
975
1233
|
</mj-collapsible-panel>
|
|
976
1234
|
`,
|
|
977
1235
|
}]
|
|
978
1236
|
}], null, null); })();
|
|
979
|
-
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MJCContractDatesPanel, { className: "MJCContractDatesPanel", filePath: "lib/form-panels/contract.panels.ts", lineNumber:
|
|
1237
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MJCContractDatesPanel, { className: "MJCContractDatesPanel", filePath: "lib/form-panels/contract.panels.ts", lineNumber: 773 }); })();
|
|
980
1238
|
/* ────────────────────────────────────────────────────────────────────────────
|
|
981
1239
|
* 4 · Lineage — change orders and supersession, read-only
|
|
982
1240
|
* ──────────────────────────────────────────────────────────────────────────── */
|
|
983
1241
|
let MJCContractLineagePanel = class MJCContractLineagePanel extends BaseFormPanel {
|
|
984
1242
|
cdr = inject(ChangeDetectorRef);
|
|
985
|
-
navigation = inject(NavigationService);
|
|
986
1243
|
/**
|
|
987
1244
|
* The whole tree, declared rather than fetched.
|
|
988
1245
|
*
|
|
@@ -1022,7 +1279,7 @@ let MJCContractLineagePanel = class MJCContractLineagePanel extends BaseFormPane
|
|
|
1022
1279
|
const key = e?.Node?.PrimaryKey;
|
|
1023
1280
|
if (!key)
|
|
1024
1281
|
return;
|
|
1025
|
-
this.
|
|
1282
|
+
this.FormComponent.OnFormNavigate({ Kind: 'record', EntityName: MJC_ENTITIES.Contract, PrimaryKey: key });
|
|
1026
1283
|
}
|
|
1027
1284
|
get ParentName() { return this.Record?.ParentContract ?? ''; }
|
|
1028
1285
|
get Count() {
|
|
@@ -1071,7 +1328,7 @@ let MJCContractLineagePanel = class MJCContractLineagePanel extends BaseFormPane
|
|
|
1071
1328
|
return ScopedRunView(this.FormComponent?.ProviderToUse);
|
|
1072
1329
|
}
|
|
1073
1330
|
static ɵfac = /*@__PURE__*/ (() => { let ɵMJCContractLineagePanel_BaseFactory; return function MJCContractLineagePanel_Factory(__ngFactoryType__) { return (ɵMJCContractLineagePanel_BaseFactory || (ɵMJCContractLineagePanel_BaseFactory = i0.ɵɵgetInheritedFactory(MJCContractLineagePanel)))(__ngFactoryType__ || MJCContractLineagePanel); }; })();
|
|
1074
|
-
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: MJCContractLineagePanel, selectors: [["mjc-contract-lineage-panel"]], features: [i0.ɵɵInheritDefinitionFeature], decls: 5, vars: 9, consts: [["SectionKey", "
|
|
1331
|
+
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: MJCContractLineagePanel, selectors: [["mjc-contract-lineage-panel"]], features: [i0.ɵɵInheritDefinitionFeature], decls: 5, vars: 9, consts: [["SectionKey", "lineage", "SectionName", "Lineage", "Icon", "fa-solid fa-sitemap", "Variant", "related-entity", 3, "BadgeCount", "Form", "FormContext"], [1, "mjc-body"], [3, "NodeDoubleClick", "Config", "ActiveRecordID"], [1, "mjc-empty"], [1, "mjc-note"]], template: function MJCContractLineagePanel_Template(rf, ctx) { if (rf & 1) {
|
|
1075
1332
|
i0.ɵɵelementStart(0, "mj-collapsible-panel", 0)(1, "div", 1);
|
|
1076
1333
|
i0.ɵɵconditionalCreate(2, MJCContractLineagePanel_Conditional_2_Template, 2, 1, "div", 1);
|
|
1077
1334
|
i0.ɵɵelementStart(3, "mj-hierarchy-tree", 2);
|
|
@@ -1089,7 +1346,7 @@ let MJCContractLineagePanel = class MJCContractLineagePanel extends BaseFormPane
|
|
|
1089
1346
|
i0.ɵɵproperty("Config", ctx.TreeConfig)("ActiveRecordID", (ctx.Record == null ? null : ctx.Record.ID) ?? undefined);
|
|
1090
1347
|
i0.ɵɵadvance();
|
|
1091
1348
|
i0.ɵɵconditional(!ctx.ParentName && !ctx.HasChildren ? 4 : -1);
|
|
1092
|
-
} }, dependencies: [CommonModule, FormsModule, BaseFormsModule,
|
|
1349
|
+
} }, dependencies: [CommonModule, FormsModule, BaseFormsModule, i1.MjCollapsiblePanelComponent, HierarchyTreeComponent], styles: ["\n /* A PINNED FLOOR, not a percentage. height:100% cannot work here: it resolves against\n .mj-forms-panel-content, which the variant sets to height:auto, and 100% of auto collapses\n straight back to auto - measured blank. AG Grid escapes this because the grid supplies its\n own intrinsic height; a plain div does not. A px min-height resolves regardless of what the\n parent computes to, and stays under the variant's own 800px cap. */\n /* DIRECT child only. As a descendant selector this also matched the nested .mjc-body wrapper\n inside the panel, so the floor applied twice and left a tall empty block above the tree. */\n mjc-contract-lineage-panel > .mjc-body {\n min-height: 440px;\n overflow-y: auto;\n }\n mjc-contract-lineage-panel mj-hierarchy-tree { display: block; min-height: 380px; }\n "], encapsulation: 2 });
|
|
1093
1350
|
};
|
|
1094
1351
|
MJCContractLineagePanel = __decorate([
|
|
1095
1352
|
RegisterClassEx(BaseFormPanel, {
|
|
@@ -1126,7 +1383,7 @@ export { MJCContractLineagePanel };
|
|
|
1126
1383
|
type: Component,
|
|
1127
1384
|
args: [{ selector: 'mjc-contract-lineage-panel', standalone: true, encapsulation: ViewEncapsulation.None, imports: [CommonModule, FormsModule, BaseFormsModule, HierarchyTreeComponent], template: `
|
|
1128
1385
|
<mj-collapsible-panel
|
|
1129
|
-
SectionKey="
|
|
1386
|
+
SectionKey="lineage"
|
|
1130
1387
|
SectionName="Lineage"
|
|
1131
1388
|
Icon="fa-solid fa-sitemap"
|
|
1132
1389
|
Variant="related-entity"
|
|
@@ -1156,12 +1413,12 @@ export { MJCContractLineagePanel };
|
|
|
1156
1413
|
|
|
1157
1414
|
@if (!ParentName && !HasChildren) {
|
|
1158
1415
|
<div class="mjc-empty">
|
|
1159
|
-
|
|
1416
|
+
No parent contract, change orders, or superseding contracts.
|
|
1160
1417
|
</div>
|
|
1161
1418
|
}
|
|
1162
1419
|
</div>
|
|
1163
1420
|
</mj-collapsible-panel>
|
|
1164
1421
|
`, styles: ["\n /* A PINNED FLOOR, not a percentage. height:100% cannot work here: it resolves against\n .mj-forms-panel-content, which the variant sets to height:auto, and 100% of auto collapses\n straight back to auto - measured blank. AG Grid escapes this because the grid supplies its\n own intrinsic height; a plain div does not. A px min-height resolves regardless of what the\n parent computes to, and stays under the variant's own 800px cap. */\n /* DIRECT child only. As a descendant selector this also matched the nested .mjc-body wrapper\n inside the panel, so the floor applied twice and left a tall empty block above the tree. */\n mjc-contract-lineage-panel > .mjc-body {\n min-height: 440px;\n overflow-y: auto;\n }\n mjc-contract-lineage-panel mj-hierarchy-tree { display: block; min-height: 380px; }\n "] }]
|
|
1165
1422
|
}], null, null); })();
|
|
1166
|
-
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MJCContractLineagePanel, { className: "MJCContractLineagePanel", filePath: "lib/form-panels/contract.panels.ts", lineNumber:
|
|
1423
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MJCContractLineagePanel, { className: "MJCContractLineagePanel", filePath: "lib/form-panels/contract.panels.ts", lineNumber: 898 }); })();
|
|
1167
1424
|
//# sourceMappingURL=contract.panels.js.map
|