@riboseinc/paneron-registry-kit 2.2.5 → 2.2.7

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.
@@ -3,7 +3,7 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.default = void 0;
6
+ exports.default = exports.ItemDetail = void 0;
7
7
 
8
8
  var _react = _interopRequireWildcard(require("react"));
9
9
 
@@ -57,34 +57,23 @@ function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj &&
57
57
  * NOTE: while generally intended as tab content handler,
58
58
  * is also reused within change request view.
59
59
  */
60
- const ItemDetail = function ({
60
+ const MaybeItemDetail = (0, _react.memo)(function ({
61
61
  uri,
62
62
  inProposalWithID
63
63
  }) {
64
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m; //const { value: itemData } = useSingleRegisterItemData(ref);
64
+ var _a, _b, _c; //const { value: itemData } = useSingleRegisterItemData(ref);
65
65
 
66
66
 
67
- const {
68
- updateObjects,
69
- makeRandomID,
70
- performOperation,
71
- isBusy
72
- } = (0, _react.useContext)(_context.DatasetContext);
73
- const {
74
- spawnTab
75
- } = (0, _react.useContext)(_context2.TabbedWorkspaceContext);
76
67
  const {
77
68
  jumpTo,
78
69
  subregisters,
79
- useRegisterItemData,
80
- activeChangeRequestID: globallyActiveCRID
70
+ useRegisterItemData
81
71
  } = (0, _react.useContext)(_BrowserCtx.BrowserCtx);
82
- const ref = (0, _itemPathUtils.useItemRef)(subregisters !== undefined, uri);
83
- const itemClass = (0, _useItemClassConfig.default)((_a = ref === null || ref === void 0 ? void 0 : ref.classID) !== null && _a !== void 0 ? _a : 'NONEXISTENT_CLASS_ID');
84
72
  const {
85
- changeRequest: activeCR,
86
- canEdit: activeCRIsEditable
73
+ changeRequest: activeCR
87
74
  } = (0, _react.useContext)(_ChangeRequestContext.ChangeRequestContext);
75
+ const ref = (0, _itemPathUtils.useItemRef)(subregisters !== undefined, uri);
76
+ const itemClass = (0, _useItemClassConfig.default)((_a = ref === null || ref === void 0 ? void 0 : ref.classID) !== null && _a !== void 0 ? _a : 'NONEXISTENT_CLASS_ID');
88
77
  const itemClassID = (_b = itemClass === null || itemClass === void 0 ? void 0 : itemClass.meta) === null || _b === void 0 ? void 0 : _b.id;
89
78
  const itemRef = ref !== null && ref !== void 0 ? ref : _types.DUMMY_REF;
90
79
  const {
@@ -98,11 +87,81 @@ const ItemDetail = function ({
98
87
  }), [itemPath]);
99
88
  const itemResponse = useRegisterItemData(itemRequest);
100
89
  const itemData = itemResponse.value[itemPath];
90
+
91
+ if (!itemClass) {
92
+ return (0, _react2.jsx)(_core.NonIdealState, {
93
+ icon: "heart-broken",
94
+ title: "Unable to show item",
95
+ description: `View for ${(_c = ref === null || ref === void 0 ? void 0 : ref.itemID) !== null && _c !== void 0 ? _c : uri} cannot be retrieved from item class configuration`
96
+ });
97
+ } else if ((0, _types.isRegisterItem)(itemData)) {
98
+ return (0, _react2.jsx)(ItemDetail, {
99
+ item: itemData,
100
+ itemRef: itemRef,
101
+ itemClass: itemClass,
102
+ inProposalWithID: inProposalWithID
103
+ });
104
+ } else if (itemResponse.isUpdating) {
105
+ return (0, _react2.jsx)("div", {
106
+ className: _core.Classes.SKELETON
107
+ }, "Loading");
108
+ } else {
109
+ // Opened using URI that points within a proposal.
110
+ // The item may or may not have been accepted.
111
+ const inCRWithID = (0, _itemPathUtils.getCRIDFromProposedItemPath)(uri);
112
+
113
+ if (inCRWithID !== null && (activeCR === null || activeCR === void 0 ? void 0 : activeCR.id) !== inCRWithID) {
114
+ return (0, _react2.jsx)(_core.NonIdealState, {
115
+ icon: "help",
116
+ title: "This item does not exist\u2026",
117
+ description: (0, _react2.jsx)(_react.default.Fragment, null, "\u2026but it might be proposed.", (0, _react2.jsx)("br", null), jumpTo ? (0, _react2.jsx)(_core.Button, {
118
+ css: (0, _react2.css)`margin: 10px;`,
119
+ intent: "primary",
120
+ onClick: () => jumpTo === null || jumpTo === void 0 ? void 0 : jumpTo(`${_protocolRegistry.Protocols.CHANGE_REQUEST}:${(0, _itemPathUtils.crIDToCRPath)(inCRWithID)}`)
121
+ }, "Go to proposal") : null)
122
+ });
123
+ } else {
124
+ const desc = itemData === null || itemData === undefined ? "does not exist or could not be deserialized" : "may use unexpected data format";
125
+ return (0, _react2.jsx)(_core.NonIdealState, {
126
+ icon: "heart-broken",
127
+ title: "Unable to show item",
128
+ description: `Item at ${itemPath} ${desc}`
129
+ });
130
+ }
131
+ }
132
+ });
133
+ const ItemDetail = (0, _react.memo)(function ({
134
+ item,
135
+ itemRef,
136
+ itemClass,
137
+ className,
138
+ inProposalWithID
139
+ }) {
140
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
141
+
142
+ const {
143
+ subregisters,
144
+ activeChangeRequestID: globallyActiveCRID
145
+ } = (0, _react.useContext)(_BrowserCtx.BrowserCtx);
146
+ const {
147
+ changeRequest: activeCR,
148
+ canEdit: activeCRIsEditable
149
+ } = (0, _react.useContext)(_ChangeRequestContext.ChangeRequestContext);
150
+ const {
151
+ updateObjects,
152
+ makeRandomID,
153
+ performOperation,
154
+ isBusy
155
+ } = (0, _react.useContext)(_context.DatasetContext);
156
+ const {
157
+ spawnTab
158
+ } = (0, _react.useContext)(_context2.TabbedWorkspaceContext);
101
159
  const [editedClarification, setEditedClarification] = (0, _react.useState)(null); //const [ diffMode, setDiffMode ] = useState<boolean>(false);
102
160
  // TODO: Implement diff mode
103
161
 
104
162
  const diffMode = false;
105
- const proposal = (_c = activeCR && activeCR.items[itemPath] ? activeCR.items[itemPath] : null) !== null && _c !== void 0 ? _c : null;
163
+ const itemPath = (0, _itemPathUtils.itemRefToItemPath)(itemRef);
164
+ const proposal = (_a = activeCR && activeCR.items[itemPath] ? activeCR.items[itemPath] : null) !== null && _a !== void 0 ? _a : null;
106
165
 
107
166
  const handleClearProposal = () => performProposalOperation('clearing draft proposal', null);
108
167
 
@@ -141,7 +200,7 @@ const ItemDetail = function ({
141
200
  }
142
201
 
143
202
  const handleSetProposal = (0, _react.useCallback)(async function _handleSetProposal(summary, proposal) {
144
- if (!activeCRIsEditable || !updateObjects || !(0, _types.isRegisterItem)(itemData)) {
203
+ if (!activeCRIsEditable || !updateObjects || !(0, _types.isRegisterItem)(item)) {
145
204
  throw new Error("Proposal isn’t editable");
146
205
  }
147
206
 
@@ -155,7 +214,7 @@ const ItemDetail = function ({
155
214
  activeCR, {
156
215
  [itemPath]: proposal
157
216
  }, proposal && (proposal === null || proposal === void 0 ? void 0 : proposal.type) !== 'amendment' && editedClarification ? {
158
- [itemPath]: { ...itemData,
217
+ [itemPath]: { ...item,
159
218
  data: editedClarification
160
219
  }
161
220
  } : {}),
@@ -163,10 +222,10 @@ const ItemDetail = function ({
163
222
  // omits oldValue for item data payloads.
164
223
  _dangerouslySkipValidation: true
165
224
  });
166
- }, [editedClarification, activeCRIsEditable, itemPath, JSON.stringify(itemData), JSON.stringify(activeCR), updateObjects]); // TODO: Very similar to `handleAdd()` in Browse sidebar menu; refactor?
225
+ }, [editedClarification, activeCRIsEditable, itemPath, item, activeCR, updateObjects]); // TODO: Very similar to `handleAdd()` in Browse sidebar menu; refactor?
167
226
 
168
227
  const handleProposeLikeThis = (0, _react.useCallback)(async function _handleProposeLikeThis() {
169
- if (!updateObjects || !makeRandomID || !activeCRIsEditable || !activeCR || !itemClass || !(0, _types.isRegisterItem)(itemData)) {
228
+ if (!updateObjects || !makeRandomID || !activeCRIsEditable || !activeCR || !itemClass || !(0, _types.isRegisterItem)(item)) {
170
229
  throw new Error("Unable to create item: likely current proposal is not editable or dataset is read-only");
171
230
  }
172
231
 
@@ -184,7 +243,7 @@ const ItemDetail = function ({
184
243
  id: itemID,
185
244
  dateAccepted: new Date(),
186
245
  status: 'valid',
187
- data: { ...itemData.data
246
+ data: { ...item.data
188
247
  }
189
248
  };
190
249
 
@@ -208,165 +267,136 @@ const ItemDetail = function ({
208
267
  } else {
209
268
  throw new Error("Newly created item did not pass validation (this is likely a bug in RegistryKit");
210
269
  }
211
- }, [updateObjects, activeCRIsEditable, itemPath, activeCR === null || activeCR === void 0 ? void 0 : activeCR.id, activeCR === null || activeCR === void 0 ? void 0 : activeCR.state, Object.entries((_d = activeCR === null || activeCR === void 0 ? void 0 : activeCR.items) !== null && _d !== void 0 ? _d : {}).flat().map(i => JSON.stringify(i)).toString(), itemData ? JSON.stringify((0, _util.normalizeObject)(itemData)) : itemData]);
212
-
213
- if (!itemClass) {
214
- return (0, _react2.jsx)(_core.NonIdealState, {
215
- icon: "heart-broken",
216
- title: "Unable to show item",
217
- description: `View for ${(_e = ref === null || ref === void 0 ? void 0 : ref.itemID) !== null && _e !== void 0 ? _e : uri} cannot be retrieved from item class configuration`
218
- });
219
- } else if ((0, _types.isRegisterItem)(itemData)) {
220
- let details;
221
-
222
- if (editedClarification !== null && activeCRIsEditable) {
223
- const EditView = itemClass.views.editView;
224
- details = (0, _react2.jsx)(EditView, {
225
- itemData: editedClarification,
226
- itemRef: itemRef,
227
- onChange: !isBusy ? newData => {
228
- setEditedClarification(newData);
229
- } : undefined
230
- });
231
- } else {
232
- const DetailView = (_f = itemClass.views.detailView) !== null && _f !== void 0 ? _f : itemClass.views.editView;
233
- details = (0, _react2.jsx)(DetailView, {
234
- itemRef: itemRef,
235
- itemData: itemData.data
236
- });
237
- } //const canAmend = activeCR && itemData.status === 'valid';
238
-
239
-
240
- const itemStatus = (0, _react2.jsx)(FormGroup, {
241
- inline: true,
242
- label: "status:",
243
- css: (0, _react2.css)`margin: 0;`
244
- }, (0, _react2.jsx)(_core.ControlGroup, {
245
- fill: true
246
- }, (0, _react2.jsx)(_core.InputGroup, {
247
- value: (proposal === null || proposal === void 0 ? void 0 : proposal.type) === 'amendment' ? `${proposal.amendmentType} proposed` : (proposal === null || proposal === void 0 ? void 0 : proposal.type) === 'addition' ? "addition proposed" : itemData.status,
248
- intent: (proposal === null || proposal === void 0 ? void 0 : proposal.type) === 'amendment' ? 'warning' : (proposal === null || proposal === void 0 ? void 0 : proposal.type) === 'addition' ? 'primary' : itemData.status === 'valid' ? 'success' : undefined,
249
- leftIcon: proposal && (proposal.type === 'amendment' || proposal.type === 'addition') ? 'asterisk' : itemData.status === 'valid' ? 'tick' : itemData.status === 'invalid' ? 'ban-circle' : 'warning-sign',
250
- readOnly: true
251
- }), activeCRIsEditable && !editedClarification ? (0, _react2.jsx)(_react.default.Fragment, null, (proposal === null || proposal === void 0 ? void 0 : proposal.type) === 'addition' ? (0, _react2.jsx)(_core.Button, {
252
- intent: "warning",
253
- title: "Remove the proposal to add this new item.",
254
- disabled: isBusy,
255
- onClick: handleClearProposal
256
- }, "Remove proposed addition") : null, (proposal === null || proposal === void 0 ? void 0 : proposal.type) === 'amendment' ? (0, _react2.jsx)(_core.Button, {
257
- intent: "warning",
258
- title: `Remove amendment (${proposal.amendmentType}) for this item from current proposal.`,
259
- disabled: isBusy,
260
- onClick: handleClearProposal
261
- }, "Clear proposed amendment") : !proposal && itemData.status === 'valid' ? (0, _react2.jsx)(_core.ButtonGroup, null, (0, _react2.jsx)(_core.Button, {
262
- intent: "primary",
263
- disabled: isBusy,
264
- onClick: handleRetire
265
- }, "Retire"), (0, _react2.jsx)(_core.Button, {
266
- intent: "primary",
267
- disabled: isBusy,
268
- onClick: handleInvalidate
269
- }, "Invalidate")) : null) : null));
270
- const supersedingItems = // It’s superseded (whether in current proposal or not)
271
- itemData.status === 'superseded' // Item is valid, proposal is editable, and no change to this item is proposed yet
272
- || activeCRIsEditable && !proposal && !editedClarification && itemData.status === 'valid' // This item is being superseded in active proposal
273
- // XXX: Redundant condition with the first one?
274
- || (proposal === null || proposal === void 0 ? void 0 : proposal.type) === 'amendment' && proposal.amendmentType === 'supersession' ? (0, _react2.jsx)(FormGroup, {
275
- inline: true,
276
- label: "superseded by: ",
277
- css: (0, _react2.css)`margin: 0;`
278
- }, (0, _react2.jsx)(_RelatedItems.RelatedItems, {
279
- availableClassIDs: [itemClass.meta.id],
280
- itemRefs: (proposal === null || proposal === void 0 ? void 0 : proposal.type) === 'amendment' && proposal.amendmentType === 'supersession' ? proposal.supersedingItemIDs.map(id => ({
281
- itemID: id,
282
- classID: itemClass.meta.id,
283
- subregisterID
284
- })) : (_g = itemData.supersededBy) !== null && _g !== void 0 ? _g : [],
285
- onChange: !isBusy && activeCRIsEditable && ((proposal === null || proposal === void 0 ? void 0 : proposal.type) === 'amendment' && proposal.amendmentType === 'supersession' || !proposal && itemData.status === 'valid') ? items => items.length > 0 ? handleSupersedeWith(items.map(ref => ref.itemID)) : handleClearProposal() : undefined
286
- })) : null;
287
- const clarificationHasChanges = JSON.stringify(editedClarification) !== JSON.stringify(itemData.data);
288
- const clarificationAction = proposal && (proposal === null || proposal === void 0 ? void 0 : proposal.type) !== 'amendment' || activeCRIsEditable && !proposal && itemData.status === 'valid' ? (0, _react2.jsx)(FormGroup, {
289
- inline: true,
290
- label: `${(_h = proposal === null || proposal === void 0 ? void 0 : proposal.type) !== null && _h !== void 0 ? _h : "clarification"}: `,
291
- css: (0, _react2.css)`margin: 0;`
292
- }, activeCRIsEditable ? (0, _react2.jsx)(_core.ButtonGroup, null, editedClarification ? (0, _react2.jsx)(_react.default.Fragment, null, (0, _react2.jsx)(_core.Button, {
293
- intent: clarificationHasChanges ? "primary" : undefined,
294
- // TODO(perf): this is expensive if renders are frequent…
295
- disabled: !clarificationHasChanges || isBusy,
296
- onClick: !proposal || (proposal === null || proposal === void 0 ? void 0 : proposal.type) === 'clarification' ? handleClarify : handleEditAddition
297
- }, "Save"), (0, _react2.jsx)(_core.Button, {
298
- onClick: () => setEditedClarification(null)
299
- }, "Do not save")) : (0, _react2.jsx)(_react.default.Fragment, null, (0, _react2.jsx)(_core.Button, {
300
- disabled: diffMode || isBusy,
301
- intent: "primary",
302
- outlined: true,
303
- onClick: () => setEditedClarification(itemData.data)
304
- }, !proposal ? "Clarify" : "Edit"), (proposal === null || proposal === void 0 ? void 0 : proposal.type) === 'clarification' ? (0, _react2.jsx)(_react.default.Fragment, null, (0, _react2.jsx)(_core.Button, {
305
- disabled: diffMode || isBusy || (proposal === null || proposal === void 0 ? void 0 : proposal.type) !== 'clarification',
306
- intent: "warning",
307
- onClick: handleClearProposal
308
- }, "Clear")) : null)) : (0, _react2.jsx)(_core.Button, {
309
- disabled: true
310
- }, (proposal === null || proposal === void 0 ? void 0 : proposal.type) === 'clarification' ? "Clarified" : "Added", " in active proposal")) : null;
311
- const proposeLikeThis = activeCRIsEditable && !editedClarification ? (0, _react2.jsx)(_core.Button, {
312
- title: "Propose a new item in current proposal, using this item as template.",
313
- icon: 'plus',
314
- disabled: isBusy,
315
- outlined: true,
316
- onClick: performOperation('duplicating item', handleProposeLikeThis)
317
- }, "Propose another like this") : null; // If there’s a CR context without active CR,
318
- // or active CR isn’t the same as the one in CR context,
319
- // then we can assume that the item is shown in proposal window
320
- // and we’d set window title to proposal’s title rather than item’s.
321
- // If there’s a CR context and active CR and they’re the same
322
- // then it *could* be that the item is shown in its own tab;
323
- // we will render proposal’s title if the item appears in the change request
324
- // (makes sense because the user *is* technically viewing a proposal then).
325
-
326
- const windowTitle = activeCR && (!globallyActiveCRID || activeCR.id !== globallyActiveCRID || activeCR.items[itemPath]) ? `Proposal ${(0, _util2.maybeEllipsizeString)(activeCR.justification, 20)}…` : `${(_j = itemClass.meta.title) !== null && _j !== void 0 ? _j : 'register item'} #${itemData.id}`;
327
- return (0, _react2.jsx)(_util2.TabContentsWithActions, {
328
- actions: (0, _react2.jsx)(_react.default.Fragment, null, (0, _react2.jsx)(FormGroup, {
329
- inline: true,
330
- labelInfo: (0, _react2.jsx)(_HelpTooltip.default, {
331
- icon: 'info-sign',
332
- content: (0, _react2.jsx)(_react.default.Fragment, null, (0, _react2.jsx)(_core.H5, null, itemClass.meta.title), (_k = itemClass.meta.description) !== null && _k !== void 0 ? _k : "No description is provided for this register item class.", (0, _react2.jsx)(_core.UL, null, (0, _react2.jsx)("li", null, "Class ID: ", itemClassID), (0, _react2.jsx)("li", null, "Subregister ID: ", subregisterID !== null && subregisterID !== void 0 ? subregisterID : 'N/A'), (0, _react2.jsx)("li", null, "UUID: ", itemID)))
333
- }),
334
- label: (0, _react2.jsx)(_react.default.Fragment, null, (0, _react2.jsx)("strong", null, itemClass.meta.title), subregisterID ? (0, _react2.jsx)("span", {
335
- title: "Subregister"
336
- }, " in ", (_m = (_l = subregisters === null || subregisters === void 0 ? void 0 : subregisters[subregisterID]) === null || _l === void 0 ? void 0 : _l.title) !== null && _m !== void 0 ? _m : subregisterID) : null),
337
- css: (0, _react2.css)`margin: 0; .bp4-form-content { display: flex; flex-flow: row wrap; gap: 10px; }`
338
- }, itemStatus, supersedingItems, clarificationAction, proposeLikeThis)),
339
- main: (0, _react2.jsx)(_core.Card, {
340
- css: (0, _react2.css)`position: absolute; inset: ${inProposalWithID ? '0' : '10px'}; overflow-y: auto;`
341
- }, (0, _react2.jsx)(_util2.RegisterHelmet, null, (0, _react2.jsx)("title", null, windowTitle)), details)
270
+ }, [updateObjects, activeCRIsEditable, itemPath, activeCR === null || activeCR === void 0 ? void 0 : activeCR.id, activeCR === null || activeCR === void 0 ? void 0 : activeCR.state, Object.entries((_b = activeCR === null || activeCR === void 0 ? void 0 : activeCR.items) !== null && _b !== void 0 ? _b : {}).flat().map(i => JSON.stringify(i)).toString(), item ? JSON.stringify((0, _util.normalizeObject)(item)) : item]);
271
+ let details;
272
+
273
+ if (editedClarification !== null && activeCRIsEditable) {
274
+ const EditView = itemClass.views.editView;
275
+ details = (0, _react2.jsx)(EditView, {
276
+ itemData: editedClarification,
277
+ itemRef: itemRef,
278
+ onChange: !isBusy ? setEditedClarification : undefined
342
279
  });
343
- } else if (itemResponse.isUpdating) {
344
- return (0, _react2.jsx)("div", {
345
- className: _core.Classes.SKELETON
346
- }, "Loading\u2026");
347
280
  } else {
348
- const inCRWithID = (0, _itemPathUtils.getCRIDFromProposedItemPath)(uri);
349
-
350
- if (inCRWithID !== null && (activeCR === null || activeCR === void 0 ? void 0 : activeCR.id) !== inCRWithID) {
351
- return (0, _react2.jsx)(_core.NonIdealState, {
352
- icon: "help",
353
- title: "This item does not exist\u2026",
354
- description: (0, _react2.jsx)(_react.default.Fragment, null, "\u2026but it might be proposed.", (0, _react2.jsx)("br", null), jumpTo ? (0, _react2.jsx)(_core.Button, {
355
- css: (0, _react2.css)`margin: 10px;`,
356
- intent: "primary",
357
- onClick: () => jumpTo === null || jumpTo === void 0 ? void 0 : jumpTo(`${_protocolRegistry.Protocols.CHANGE_REQUEST}:${(0, _itemPathUtils.crIDToCRPath)(inCRWithID)}`)
358
- }, "Go to proposal") : null)
359
- });
360
- } else {
361
- const desc = itemData === null || itemData === undefined ? "does not exist or could not be deserialized" : "may use unexpected data format";
362
- return (0, _react2.jsx)(_core.NonIdealState, {
363
- icon: "heart-broken",
364
- title: "Unable to show item",
365
- description: `Item at ${itemPath} ${desc}`
366
- });
367
- }
281
+ const DetailView = (_c = itemClass.views.detailView) !== null && _c !== void 0 ? _c : itemClass.views.editView;
282
+ details = (0, _react2.jsx)(DetailView, {
283
+ itemRef: itemRef,
284
+ itemData: item.data
285
+ });
368
286
  }
369
- };
287
+
288
+ console.debug("Rendering RegisterItem view"); //const canAmend = activeCR && itemData.status === 'valid';
289
+
290
+ const itemStatus = (0, _react2.jsx)(FormGroup, {
291
+ inline: true,
292
+ label: "status:",
293
+ css: (0, _react2.css)`margin: 0;`
294
+ }, (0, _react2.jsx)(_core.ControlGroup, {
295
+ fill: true
296
+ }, (0, _react2.jsx)(_core.InputGroup, {
297
+ value: (proposal === null || proposal === void 0 ? void 0 : proposal.type) === 'amendment' ? `${proposal.amendmentType} proposed` : (proposal === null || proposal === void 0 ? void 0 : proposal.type) === 'addition' ? "addition proposed" : item.status,
298
+ intent: (proposal === null || proposal === void 0 ? void 0 : proposal.type) === 'amendment' ? 'warning' : (proposal === null || proposal === void 0 ? void 0 : proposal.type) === 'addition' ? 'primary' : item.status === 'valid' ? 'success' : undefined,
299
+ leftIcon: proposal && (proposal.type === 'amendment' || proposal.type === 'addition') ? 'asterisk' : item.status === 'valid' ? 'tick' : item.status === 'invalid' ? 'ban-circle' : 'warning-sign',
300
+ readOnly: true
301
+ }), activeCRIsEditable && !editedClarification ? (0, _react2.jsx)(_react.default.Fragment, null, (proposal === null || proposal === void 0 ? void 0 : proposal.type) === 'addition' ? (0, _react2.jsx)(_core.Button, {
302
+ intent: "warning",
303
+ title: "Remove the proposal to add this new item.",
304
+ disabled: isBusy,
305
+ onClick: handleClearProposal
306
+ }, "Remove proposed addition") : null, (proposal === null || proposal === void 0 ? void 0 : proposal.type) === 'amendment' ? (0, _react2.jsx)(_core.Button, {
307
+ intent: "warning",
308
+ title: `Remove amendment (${proposal.amendmentType}) for this item from current proposal.`,
309
+ disabled: isBusy,
310
+ onClick: handleClearProposal
311
+ }, "Clear proposed amendment") : !proposal && item.status === 'valid' ? (0, _react2.jsx)(_core.ButtonGroup, null, (0, _react2.jsx)(_core.Button, {
312
+ intent: "primary",
313
+ disabled: isBusy,
314
+ onClick: handleRetire
315
+ }, "Retire"), (0, _react2.jsx)(_core.Button, {
316
+ intent: "primary",
317
+ disabled: isBusy,
318
+ onClick: handleInvalidate
319
+ }, "Invalidate")) : null) : null)); // It’s superseded (whether in current proposal or not)
320
+
321
+ const isSuperseded = item.status === 'superseded'; // Item is valid, proposal is editable, and no change to this item is proposed yet
322
+
323
+ const canBeSuperseded = activeCRIsEditable && !proposal && !editedClarification && item.status === 'valid'; // This item is being superseded in active proposal
324
+ // XXX: May be redundant with `isSuperseded`?
325
+
326
+ const isBeingSuperseded = (proposal === null || proposal === void 0 ? void 0 : proposal.type) === 'amendment' && proposal.amendmentType === 'supersession';
327
+ const supersedingItems = isSuperseded || canBeSuperseded || isBeingSuperseded ? (0, _react2.jsx)(FormGroup, {
328
+ inline: true,
329
+ label: "superseded by: ",
330
+ css: (0, _react2.css)`margin: 0;`
331
+ }, (0, _react2.jsx)(_RelatedItems.RelatedItems, {
332
+ availableClassIDs: [itemClass.meta.id],
333
+ itemRefs: (proposal === null || proposal === void 0 ? void 0 : proposal.type) === 'amendment' && proposal.amendmentType === 'supersession' ? proposal.supersedingItemIDs.map(id => ({
334
+ itemID: id,
335
+ // Superseding items are always of the same class
336
+ classID: itemClass.meta.id,
337
+ // Superseding items are always in the same subregister
338
+ subregisterID: itemRef.subregisterID
339
+ })) : (_d = item.supersededBy) !== null && _d !== void 0 ? _d : [],
340
+ onChange: !isBusy && activeCRIsEditable && ((proposal === null || proposal === void 0 ? void 0 : proposal.type) === 'amendment' && proposal.amendmentType === 'supersession' || !proposal && item.status === 'valid') ? items => items.length > 0 ? handleSupersedeWith(items.map(ref => ref.itemID)) : handleClearProposal() : undefined
341
+ })) : null;
342
+ const clarificationHasChanges = JSON.stringify(editedClarification) !== JSON.stringify(item.data);
343
+ const clarificationAction = proposal && (proposal === null || proposal === void 0 ? void 0 : proposal.type) !== 'amendment' || activeCRIsEditable && !proposal && item.status === 'valid' ? (0, _react2.jsx)(FormGroup, {
344
+ inline: true,
345
+ label: `${(_e = proposal === null || proposal === void 0 ? void 0 : proposal.type) !== null && _e !== void 0 ? _e : "clarification"}: `,
346
+ css: (0, _react2.css)`margin: 0;`
347
+ }, activeCRIsEditable ? (0, _react2.jsx)(_core.ButtonGroup, null, editedClarification ? (0, _react2.jsx)(_react.default.Fragment, null, (0, _react2.jsx)(_core.Button, {
348
+ intent: clarificationHasChanges ? "primary" : undefined,
349
+ // TODO(perf): this is expensive if renders are frequent…
350
+ disabled: !clarificationHasChanges || isBusy,
351
+ onClick: !proposal || (proposal === null || proposal === void 0 ? void 0 : proposal.type) === 'clarification' ? handleClarify : handleEditAddition
352
+ }, "Save"), (0, _react2.jsx)(_core.Button, {
353
+ onClick: () => setEditedClarification(null)
354
+ }, "Do not save")) : (0, _react2.jsx)(_react.default.Fragment, null, (0, _react2.jsx)(_core.Button, {
355
+ disabled: diffMode || isBusy,
356
+ intent: "primary",
357
+ outlined: true,
358
+ onClick: () => setEditedClarification(item.data)
359
+ }, !proposal ? "Clarify" : "Edit"), (proposal === null || proposal === void 0 ? void 0 : proposal.type) === 'clarification' ? (0, _react2.jsx)(_react.default.Fragment, null, (0, _react2.jsx)(_core.Button, {
360
+ disabled: diffMode || isBusy || (proposal === null || proposal === void 0 ? void 0 : proposal.type) !== 'clarification',
361
+ intent: "warning",
362
+ onClick: handleClearProposal
363
+ }, "Clear")) : null)) : (0, _react2.jsx)(_core.Button, {
364
+ disabled: true
365
+ }, (proposal === null || proposal === void 0 ? void 0 : proposal.type) === 'clarification' ? "Clarified" : "Added", " in active proposal")) : null;
366
+ const proposeLikeThis = activeCRIsEditable && !editedClarification ? (0, _react2.jsx)(_core.Button, {
367
+ title: "Propose a new item in current proposal, using this item as template.",
368
+ icon: 'plus',
369
+ disabled: isBusy,
370
+ outlined: true,
371
+ onClick: performOperation('duplicating item', handleProposeLikeThis)
372
+ }, "Propose another like this") : null; // If there’s a CR context without active CR,
373
+ // or active CR isn’t the same as the one in CR context,
374
+ // then we can assume that the item is shown in proposal window
375
+ // and we’d set window title to proposal’s title rather than item’s.
376
+ // If there’s a CR context and active CR and they’re the same
377
+ // then it *could* be that the item is shown in its own tab;
378
+ // we will render proposal’s title if the item appears in the change request
379
+ // (makes sense because the user *is* technically viewing a proposal then).
380
+
381
+ const windowTitle = activeCR && (!globallyActiveCRID || activeCR.id !== globallyActiveCRID || activeCR.items[itemPath]) ? `Proposal ${(0, _util2.maybeEllipsizeString)(activeCR.justification, 20)}…` : `${(_f = itemClass.meta.title) !== null && _f !== void 0 ? _f : 'register item'} #${item.id}`;
382
+ return (0, _react2.jsx)(_util2.TabContentsWithActions, {
383
+ actions: (0, _react2.jsx)(_react.default.Fragment, null, (0, _react2.jsx)(FormGroup, {
384
+ inline: true,
385
+ labelInfo: (0, _react2.jsx)(_HelpTooltip.default, {
386
+ icon: 'info-sign',
387
+ content: (0, _react2.jsx)(_react.default.Fragment, null, (0, _react2.jsx)(_core.H5, null, itemClass.meta.title), (_g = itemClass.meta.description) !== null && _g !== void 0 ? _g : "No description is provided for this register item class.", (0, _react2.jsx)(_core.UL, null, (0, _react2.jsx)("li", null, "Class ID: ", itemClass.meta.id), (0, _react2.jsx)("li", null, "Subregister ID: ", (_h = itemRef.subregisterID) !== null && _h !== void 0 ? _h : 'N/A'), (0, _react2.jsx)("li", null, "UUID: ", itemRef.itemID)))
388
+ }),
389
+ label: (0, _react2.jsx)(_react.default.Fragment, null, (0, _react2.jsx)("strong", null, itemClass.meta.title), itemRef.subregisterID ? (0, _react2.jsx)("span", {
390
+ title: "Subregister"
391
+ }, " in ", (_k = (_j = subregisters === null || subregisters === void 0 ? void 0 : subregisters[itemRef.subregisterID]) === null || _j === void 0 ? void 0 : _j.title) !== null && _k !== void 0 ? _k : itemRef.subregisterID) : null),
392
+ css: (0, _react2.css)`margin: 0; .bp4-form-content { display: flex; flex-flow: row wrap; gap: 10px; }`
393
+ }, itemStatus, supersedingItems, clarificationAction, proposeLikeThis)),
394
+ main: (0, _react2.jsx)(_core.Card, {
395
+ css: (0, _react2.css)`position: absolute; inset: ${inProposalWithID ? '0' : '10px'}; overflow-y: auto;`
396
+ }, (0, _react2.jsx)(_util2.RegisterHelmet, null, (0, _react2.jsx)("title", null, windowTitle)), details)
397
+ });
398
+ });
399
+ exports.ItemDetail = ItemDetail;
370
400
 
371
401
  const ItemTitle = function ({
372
402
  uri
@@ -394,7 +424,7 @@ const ItemTitle = function ({
394
424
  };
395
425
 
396
426
  var _default = {
397
- main: ItemDetail,
427
+ main: MaybeItemDetail,
398
428
  title: ItemTitle
399
429
  };
400
430
  exports.default = _default;