@riboseinc/paneron-registry-kit 2.2.10 → 2.2.11

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.
Files changed (61) hide show
  1. package/index.js +18 -0
  2. package/index.js.map +1 -1
  3. package/package.json +2 -2
  4. package/types/cr.d.ts +18 -0
  5. package/types/cr.js +37 -1
  6. package/types/cr.js.map +1 -1
  7. package/types/item.d.ts +1 -1
  8. package/types/item.js.map +1 -1
  9. package/types/stakeholder.d.ts +3 -1
  10. package/types/stakeholder.js +20 -0
  11. package/types/stakeholder.js.map +1 -1
  12. package/views/AnnotatedChange.js +7 -5
  13. package/views/AnnotatedChange.js.map +1 -1
  14. package/views/GenericRelatedItemView.js +4 -47
  15. package/views/GenericRelatedItemView.js.map +1 -1
  16. package/views/ItemDrawer.d.ts +11 -0
  17. package/views/ItemDrawer.js +69 -0
  18. package/views/ItemDrawer.js.map +1 -0
  19. package/views/change-request/ChangeRequestContext.d.ts +17 -1
  20. package/views/change-request/ChangeRequestContext.js +29 -5
  21. package/views/change-request/ChangeRequestContext.js.map +1 -1
  22. package/views/change-request/Proposals.d.ts +2 -0
  23. package/views/change-request/Proposals.js +116 -80
  24. package/views/change-request/Proposals.js.map +1 -1
  25. package/views/change-request/Summary.d.ts +12 -0
  26. package/views/change-request/Summary.js +59 -0
  27. package/views/change-request/Summary.js.map +1 -0
  28. package/views/change-request/TransitionHistory.d.ts +30 -0
  29. package/views/change-request/TransitionHistory.js +307 -0
  30. package/views/change-request/TransitionHistory.js.map +1 -0
  31. package/views/change-request/TransitionOptions.d.ts +38 -0
  32. package/views/{detail/ChangeRequest/transitions.js → change-request/TransitionOptions.js} +61 -51
  33. package/views/change-request/TransitionOptions.js.map +1 -0
  34. package/views/change-request/objectChangeset.d.ts +1 -1
  35. package/views/change-request/objectChangeset.js +1 -1
  36. package/views/change-request/objectChangeset.js.map +1 -1
  37. package/views/detail/ChangeRequest/index.js +129 -142
  38. package/views/detail/ChangeRequest/index.js.map +1 -1
  39. package/views/detail/RegisterHome/MetaSummary.d.ts +9 -0
  40. package/views/detail/RegisterHome/MetaSummary.js +35 -0
  41. package/views/detail/RegisterHome/MetaSummary.js.map +1 -0
  42. package/views/detail/RegisterHome/Proposal.d.ts +24 -0
  43. package/views/detail/RegisterHome/Proposal.js +228 -0
  44. package/views/detail/RegisterHome/Proposal.js.map +1 -0
  45. package/views/detail/RegisterHome/index.js +427 -137
  46. package/views/detail/RegisterHome/index.js.map +1 -1
  47. package/views/detail/RegisterItem/index.d.ts +2 -3
  48. package/views/detail/RegisterItem/index.js +239 -140
  49. package/views/detail/RegisterItem/index.js.map +1 -1
  50. package/views/detail/RegisterMeta/RegisterMetaForm.js +37 -45
  51. package/views/detail/RegisterMeta/RegisterMetaForm.js.map +1 -1
  52. package/views/detail/RegisterMeta/index.js +14 -11
  53. package/views/detail/RegisterMeta/index.js.map +1 -1
  54. package/views/diffing/InlineDiff.d.ts +27 -1
  55. package/views/diffing/InlineDiff.js +113 -2
  56. package/views/diffing/InlineDiff.js.map +1 -1
  57. package/views/util.d.ts +36 -2
  58. package/views/util.js +203 -2
  59. package/views/util.js.map +1 -1
  60. package/views/detail/ChangeRequest/transitions.d.ts +0 -28
  61. package/views/detail/ChangeRequest/transitions.js.map +0 -1
@@ -5,7 +5,7 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.default = void 0;
7
7
 
8
- var _react = _interopRequireWildcard(require("react"));
8
+ var _react = require("react");
9
9
 
10
10
  var _react2 = require("@emotion/react");
11
11
 
@@ -13,192 +13,482 @@ var _core = require("@blueprintjs/core");
13
13
 
14
14
  var _context = require("@riboseinc/paneron-extension-kit/context");
15
15
 
16
+ var _util = require("@riboseinc/paneron-extension-kit/util");
17
+
16
18
  var _context2 = require("@riboseinc/paneron-extension-kit/widgets/TabbedWorkspace/context");
17
19
 
18
20
  var _BrowserCtx = require("../../BrowserCtx");
19
21
 
20
- var _RegisterStakeholder = require("../../RegisterStakeholder");
22
+ var _ChangeRequestContext = require("../../change-request/ChangeRequestContext");
23
+
24
+ var _itemPathUtils = require("../../itemPathUtils");
21
25
 
22
26
  var _objectChangeset = require("../../change-request/objectChangeset");
23
27
 
24
28
  var _cr = require("../../../types/cr");
25
29
 
30
+ var _TransitionOptions = require("../../change-request/TransitionOptions");
31
+
32
+ var _stakeholder = require("../../../types/stakeholder");
33
+
26
34
  var _protocolRegistry = require("../../protocolRegistry");
27
35
 
28
- var _itemPathUtils = require("../../itemPathUtils");
36
+ var _MetaSummary = _interopRequireDefault(require("./MetaSummary"));
29
37
 
30
- function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
38
+ var _util2 = require("../../util");
31
39
 
32
- function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
40
+ var _Proposal = require("./Proposal");
41
+
42
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
33
43
 
34
44
  /** @jsx jsx */
35
45
 
36
46
  /** @jsxFrag React.Fragment */
37
47
  //import { Helmet } from 'react-helmet';
38
48
  const RegisterHome = function () {
39
- var _a, _b, _c, _d;
49
+ var _a;
40
50
 
41
51
  const {
42
52
  spawnTab
43
53
  } = (0, _react.useContext)(_context2.TabbedWorkspaceContext);
44
54
  const {
45
- customViews,
55
+ //customViews,
46
56
  registerMetadata,
47
57
  stakeholder,
48
- offline,
49
- itemClasses
58
+ // offline,
59
+ itemClasses,
60
+ setActiveChangeRequestID
50
61
  } = (0, _react.useContext)(_BrowserCtx.BrowserCtx);
62
+ const {
63
+ changeRequest: activeCR,
64
+ canDelete,
65
+ deleteCR
66
+ } = (0, _react.useContext)(_ChangeRequestContext.ChangeRequestContext);
51
67
  const {
52
68
  requestFileFromFilesystem,
53
69
  makeRandomID,
54
70
  getObjectData,
55
71
  updateObjects,
56
72
  performOperation,
57
- getMapReducedData
73
+ isBusy,
74
+ getMapReducedData,
75
+ useMapReducedData
58
76
  } = (0, _react.useContext)(_context.DatasetContext);
59
- const [newProposalIdea, setNewProposalIdea] = (0, _react.useState)('');
60
77
  const registerVersion = registerMetadata === null || registerMetadata === void 0 ? void 0 : registerMetadata.version;
61
- const canCreateCR = stakeholder && stakeholder.role && ((_a = stakeholder.gitServerUsername) === null || _a === void 0 ? void 0 : _a.trim()) !== '' && makeRandomID && updateObjects && ((_b = registerVersion === null || registerVersion === void 0 ? void 0 : registerVersion.id) !== null && _b !== void 0 ? _b : '').trim() !== '';
62
-
63
- async function createCR(justification) {
64
- if (canCreateCR) {
65
- const id = await makeRandomID();
66
- await updateObjects({
67
- commitMessage: "start new proposal",
68
- objectChangeset: (0, _objectChangeset.newCRObjectChangeset)(id, justification, registerVersion, stakeholder.gitServerUsername)
69
- });
70
- return id;
78
+ const getNewEmptyCRChangeset = (0, _react.useMemo)(() => {
79
+ if (makeRandomID && stakeholder && (0, _stakeholder.canCreateCR)(stakeholder)) {
80
+ return async function getNewEmptyCRChangeset(newIdea) {
81
+ const crID = await makeRandomID();
82
+ return [(0, _objectChangeset.newCRObjectChangeset)(crID, newIdea, registerVersion, stakeholder.gitServerUsername), crID];
83
+ };
71
84
  } else {
72
- throw new Error("Unable to create proposal: read-only dataset");
85
+ return undefined;
73
86
  }
74
- }
87
+ }, [makeRandomID, stakeholder, registerVersion]);
88
+ const getImportedCRChangeset = (0, _react.useMemo)(() => {
89
+ if (requestFileFromFilesystem && stakeholder && (0, _stakeholder.canImportCR)(stakeholder)) {
90
+ return async function getImportedCRChangeset() {
91
+ const data = await requestFileFromFilesystem({
92
+ prompt: "Select one register proposal JSON file",
93
+ filters: [{
94
+ name: "JSON files",
95
+ extensions: ['.json']
96
+ }]
97
+ });
98
+ const fileData = Object.values(data)[0];
75
99
 
76
- async function handleNewProposal() {
77
- if (newProposalIdea) {
78
- const crID = await performOperation("creating proposal", createCR)(newProposalIdea);
79
- setNewProposalIdea('');
80
- spawnTab(`${_protocolRegistry.Protocols.CHANGE_REQUEST}:${(0, _itemPathUtils.crIDToCRPath)(crID)}`);
81
- }
82
- }
100
+ if (!fileData) {
101
+ throw new Error("No file was selected");
102
+ }
83
103
 
84
- async function getCRImportChangeset() {
85
- if (!requestFileFromFilesystem) {
86
- throw new Error("Cannot request file from filesystem");
87
- }
104
+ if ((0, _cr.isImportableCR)(fileData)) {
105
+ try {
106
+ const [changeset, crID] = await (0, _objectChangeset.importedProposalToCRObjectChangeset)(fileData, itemClasses, stakeholder.gitServerUsername, getObjectData, async function findObjects(predicate) {
107
+ const result = await getMapReducedData({
108
+ chains: {
109
+ _: {
110
+ mapFunc: `
111
+ const data = value.data;
112
+ if (data && (${predicate})) {
113
+ emit({ objectPath: key, objectData: value });
114
+ }
115
+ `
116
+ }
117
+ }
118
+ }); // NOTE: map returns an empty object if there’re no items,
119
+ // but we promise to return a list.
88
120
 
89
- const data = await requestFileFromFilesystem({
90
- prompt: "Select one register proposal JSON file",
91
- filters: [{
92
- name: "JSON files",
93
- extensions: ['.json']
94
- }]
95
- });
96
- const fileData = Object.values(data)[0];
97
-
98
- if (!fileData) {
99
- throw new Error("No file was selected");
100
- }
101
-
102
- if ((0, _cr.isImportableCR)(fileData)) {
103
- const crID = fileData.proposalDraft.id;
104
-
105
- try {
106
- const changeset = await (0, _objectChangeset.importedProposalToCRObjectChangeset)(fileData, itemClasses, stakeholder.gitServerUsername, getObjectData, async function findObjects(predicate) {
107
- const result = await getMapReducedData({
108
- chains: {
109
- _: {
110
- mapFunc: `
111
- const data = value.data;
112
- if (data && (${predicate})) {
113
- emit({ objectPath: key, objectData: value });
114
- }
115
- `
121
+ if (!Array.isArray(result._)) {
122
+ return [];
116
123
  }
117
- }
118
- }); // NOTE: map returns an empty object if there’re no items,
119
- // but we promise to return a list.
120
124
 
121
- if (!Array.isArray(result._)) {
122
- return [];
125
+ return result._;
126
+ });
127
+ return [changeset, crID];
128
+ } catch (e) {
129
+ throw new Error("Error reading proposal data");
123
130
  }
131
+ } else {
132
+ throw new Error("Invalid proposal format");
133
+ }
134
+ };
135
+ } else {
136
+ return undefined;
137
+ }
138
+ }, [getMapReducedData, requestFileFromFilesystem, getObjectData, stakeholder]);
139
+ const [importCR, createCR] = (0, _react.useMemo)(() => {
140
+ if (updateObjects && setActiveChangeRequestID && !isBusy) {
141
+ return [getImportedCRChangeset ? performOperation('importing proposal', async function () {
142
+ const [objectChangeset, crID] = await getImportedCRChangeset();
143
+ await updateObjects({
144
+ commitMessage: 'import proposal',
145
+ objectChangeset
146
+ });
147
+ setActiveChangeRequestID(crID);
148
+ }) : undefined, getNewEmptyCRChangeset ? performOperation('creating blank proposal', async function (newIdea) {
149
+ const [objectChangeset, crID] = await getNewEmptyCRChangeset(newIdea);
150
+ await updateObjects({
151
+ commitMessage: `start new empty proposal ${newIdea}`,
152
+ objectChangeset
153
+ });
154
+ setActiveChangeRequestID(crID);
155
+ }) : undefined];
156
+ } else {
157
+ return [undefined, undefined];
158
+ }
159
+ }, [isBusy, performOperation, updateObjects, getImportedCRChangeset, getNewEmptyCRChangeset]); // Actionable proposals v2
124
160
 
125
- return result._;
161
+ const proposalGroups = (0, _react.useMemo)(() => (stakeholder === null || stakeholder === void 0 ? void 0 : stakeholder.role) ? getActionableProposalGroupsForRole(stakeholder.role) : null, [stakeholder === null || stakeholder === void 0 ? void 0 : stakeholder.role]);
162
+ const actionableProposalsResult = useMapReducedData({
163
+ chains: (proposalGroups !== null && proposalGroups !== void 0 ? proposalGroups : []).map(([label,, queryGetter]) => {
164
+ const query = queryGetter(stakeholder);
165
+ const predicateFunc = `
166
+ const objPath = key, obj = value;
167
+ return ((${CR_BASE_QUERY}) && (${query}));
168
+ `;
169
+ const mapFunc = `emit(value);`;
170
+ return {
171
+ [label]: {
172
+ mapFunc,
173
+ predicateFunc
174
+ }
175
+ };
176
+ }).reduce((prev, curr) => ({ ...prev,
177
+ ...curr
178
+ }), {})
179
+ });
180
+ const actionableProposals = (0, _react.useMemo)(() => Object.entries(actionableProposalsResult.value).map(([chainID, chainResult]) => [chainID, (Array.isArray(chainResult) ? chainResult : undefined) || undefined]), [actionableProposalsResult.value]);
181
+ const handleRefreshProposals = actionableProposalsResult.refresh; // Actionable proposals
182
+ // const [actionableProposals, setActionableProposals] =
183
+ // useState<[string, CR[] | undefined][]>([]);
184
+ // const [reqCounter, setReqCounter] = useState(1);
185
+ // useEffect(() => {
186
+ // let cancelled = false;
187
+ // if (stakeholder) {
188
+ // const proposalGroups = getActionableProposalGroupsForRole(stakeholder.role);
189
+ // setActionableProposals(proposalGroups.map(([groupLabel, ]) => [groupLabel, undefined]));
190
+ // async function updateItems([ groupLabel, , queryGetter ]: ActionableProposalGroup) {
191
+ // const query = queryGetter(stakeholder);
192
+ // const mapFunc = `
193
+ // const objPath = key, obj = value;
194
+ // if ((${CR_BASE_QUERY}) && (${query})) {
195
+ // emit(obj);
196
+ // }
197
+ // `;
198
+ // const result = await getMapReducedData({
199
+ // chains: { _: { mapFunc } },
200
+ // });
201
+ // if (!Array.isArray(result._)) {
202
+ // console.error("Weird result", result);
203
+ // }
204
+ // if (!cancelled) {
205
+ // setActionableProposals(previousGroups =>
206
+ // previousGroups.map(([previousGroupLabel, previousProposals]) =>
207
+ // previousGroupLabel === groupLabel
208
+ // ? [previousGroupLabel, Array.isArray(result._) ? result._ : []]
209
+ // : [previousGroupLabel, previousProposals]
210
+ // )
211
+ // );
212
+ // }
213
+ // };
214
+ // proposalGroups.map(updateItems);
215
+ // } else {
216
+ // setActionableProposals([]);
217
+ // }
218
+ // return function cleanUp() { cancelled = true; };
219
+ // }, [stakeholder, reqCounter, getMapReducedData]);
220
+ // const handleRefreshProposals = useCallback(
221
+ // (() => setReqCounter(c => c + 1)),
222
+ // [setReqCounter]);
223
+ // TODO: Move to action bar
224
+ // const customActions = useMemo(() => customViews.map(cv => ({
225
+ // key: cv.id,
226
+ // text: cv.label,
227
+ // title: cv.description,
228
+ // icon: cv.icon,
229
+ // onClick: () => spawnTab(`${Protocols.CUSTOM_VIEW}:${cv.id}/index`),
230
+ // })), [spawnTab, customViews]);
231
+
232
+ const [createMode, setCreateMode] = (0, _react.useState)(false); //const canStakeholderCreateCRs = stakeholder && canCreateCR(stakeholder);
233
+
234
+ const handleSelectProposal = (0, _react.useMemo)(() => {
235
+ return setActiveChangeRequestID && !isBusy ? function (crid) {
236
+ setActiveChangeRequestID === null || setActiveChangeRequestID === void 0 ? void 0 : setActiveChangeRequestID(crid);
237
+ } : undefined;
238
+ }, [setActiveChangeRequestID, isBusy]);
239
+ const proposalBlockActions = (0, _react.useMemo)(() => {
240
+ const actions = [];
241
+
242
+ if (activeCR) {
243
+ actions.push({
244
+ text: "Export proposal",
245
+ onClick: () => void 0,
246
+ icon: 'export',
247
+ disabled: true
248
+ });
249
+ actions.push({
250
+ text: "Exit proposal",
251
+ icon: 'log-out',
252
+ intent: 'danger',
253
+ disabled: isBusy,
254
+ onClick: setActiveChangeRequestID ? () => setActiveChangeRequestID === null || setActiveChangeRequestID === void 0 ? void 0 : setActiveChangeRequestID(null) : undefined
255
+ });
256
+ } else {
257
+ if (stakeholder && (0, _stakeholder.canCreateCR)(stakeholder)) {
258
+ actions.push({
259
+ text: "Create blank proposal",
260
+ onClick: !createMode ? () => setCreateMode(true) : undefined,
261
+ disabled: !createCR,
262
+ active: createMode,
263
+ selected: createMode,
264
+ icon: 'add',
265
+ intent: actionableProposals.length < 1 ? 'primary' : undefined
126
266
  });
127
- return [changeset, crID];
128
- } catch (e) {
129
- throw new Error("Error reading proposal data");
130
267
  }
268
+
269
+ if (stakeholder && (0, _stakeholder.canImportCR)(stakeholder)) {
270
+ actions.push({
271
+ text: "Import proposal",
272
+ onClick: importCR,
273
+ disabled: !importCR || createMode,
274
+ icon: 'import',
275
+ intent: actionableProposals.length < 1 ? 'primary' : undefined
276
+ });
277
+ }
278
+ }
279
+
280
+ return actions;
281
+ }, [!activeCR, createMode, importCR, createCR, isBusy, actionableProposals.length < 1]);
282
+ const handleCreate = (0, _react.useMemo)(() => createCR && createMode ? async function (idea) {
283
+ if (idea && createCR) {
284
+ await createCR(idea);
285
+ }
286
+
287
+ setCreateMode(false);
288
+ } : undefined, [createMode, createCR]);
289
+ const proposalBlock = (0, _react.useMemo)(() => {
290
+ if (registerMetadata
291
+ /*&& actionableProposals.find(p => p[1] && p[1].length > 0)*/
292
+ ) {
293
+ return (0, _react2.jsx)(HomeBlock, {
294
+ View: _Proposal.Proposals,
295
+ key: "proposal dashboard",
296
+ description: "Actionable proposals",
297
+ css: (0, _react2.css)`
298
+ height: 300px;
299
+ flex-basis: calc(50% - 10px);
300
+ flex-grow: 1;
301
+ `,
302
+ props: {
303
+ register: registerMetadata,
304
+ actionableProposals,
305
+ createMode,
306
+ onCreate: handleCreate,
307
+ onRefreshProposals: handleRefreshProposals,
308
+ onSelectProposal: handleSelectProposal
309
+ },
310
+ actions: proposalBlockActions
311
+ });
131
312
  } else {
132
- throw new Error("Invalid proposal format");
313
+ return null;
133
314
  }
134
- }
315
+ }, [createMode, registerMetadata, proposalBlockActions, handleSelectProposal, handleCreate, (0, _util.toJSONNormalized)(actionableProposals)]);
316
+ const activeCRBlock = (0, _react.useMemo)(() => {
317
+ if (activeCR && registerMetadata) {
318
+ const actions = stakeholder && (0, _TransitionOptions.canBeTransitionedBy)(stakeholder, activeCR) ? [
319
+ /*{
320
+ // Action is taken from within the widget.
321
+ text: "Take action",
322
+ onClick: () => void 0,
323
+ icon: 'take-action',
324
+ intent: 'primary',
325
+ }*/
326
+ ] : canDelete ? [{
327
+ text: "Delete this proposal draft",
328
+ onClick: deleteCR,
329
+ disabled: !deleteCR,
330
+ icon: 'delete',
331
+ intent: 'danger'
332
+ }] : [];
333
+ actions.push({
334
+ text: "Open in new window",
335
+ onClick: async () => spawnTab(`${_protocolRegistry.Protocols.CHANGE_REQUEST}:${(0, _itemPathUtils.crIDToCRPath)(activeCR.id)}`)
336
+ });
337
+ return (0, _react2.jsx)(HomeBlock, {
338
+ View: _Proposal.CurrentProposal,
339
+ description: "Active proposal",
340
+ props: {
341
+ proposal: activeCR,
342
+ stakeholder,
343
+ register: registerMetadata
344
+ },
345
+ css: (0, _react2.css)`
346
+ height: 300px;
347
+ flex-basis: calc(50% - 10px);
348
+ flex-grow: 1;
349
+ `,
350
+ actions: actions
351
+ });
352
+ } else {
353
+ return null;
354
+ }
355
+ }, [activeCR, registerMetadata, canDelete, deleteCR, stakeholder]);
356
+ const registerMetaBlock = (0, _react.useMemo)(() => {
357
+ if (!activeCRBlock && stakeholder) {
358
+ return (0, _react2.jsx)(HomeBlock, {
359
+ View: _MetaSummary.default,
360
+ description: "Register summary",
361
+ props: registerMetadata ? {
362
+ register: registerMetadata,
363
+ style: {
364
+ padding: '10px 12px 0 12px',
365
+ flexGrow: 1,
366
+ flexShrink: 0
367
+ }
368
+ } : registerMetadata,
369
+ error: registerMetadata === null ? "Failed to load register metadata" : undefined,
370
+ css: (0, _react2.css)`
371
+ height: 300px;
372
+ flex-basis: calc(50% - 10px);
373
+ flex-grow: 1;
374
+ `,
375
+ actions: [{
376
+ text: "View or edit register metadata",
377
+ onClick: () => spawnTab(_protocolRegistry.Protocols.REGISTER_META),
378
+ icon: 'properties'
379
+ }]
380
+ });
381
+ } else {
382
+ return null;
383
+ }
384
+ }, [!activeCRBlock, registerMetadata, stakeholder]);
385
+ return (0, _react2.jsx)(_util2.TabContentsWithHeader, {
386
+ title: (_a = registerMetadata === null || registerMetadata === void 0 ? void 0 : registerMetadata.name) !== null && _a !== void 0 ? _a : 'Register',
387
+ layout: "card-grid"
388
+ }, activeCRBlock !== null && activeCRBlock !== void 0 ? activeCRBlock : registerMetaBlock, proposalBlock);
389
+ };
135
390
 
136
- async function handleImportProposal() {
137
- const [objectChangeset, crID] = await performOperation('reading proposal data', getCRImportChangeset)();
138
- await performOperation('creating proposal', updateObjects !== null && updateObjects !== void 0 ? updateObjects : async () => {
139
- throw new Error("Read-only dataset");
140
- })({
141
- commitMessage: "import proposal",
142
- objectChangeset
143
- });
144
- setNewProposalIdea('');
145
- spawnTab(`${_protocolRegistry.Protocols.CHANGE_REQUEST}:${(0, _itemPathUtils.crIDToCRPath)(crID)}`);
146
- }
391
+ var _default = RegisterHome;
392
+ exports.default = _default;
393
+
394
+ function HomeBlock({
395
+ View,
396
+ description,
397
+ props,
398
+ error,
399
+ actions,
400
+ className
401
+ }) {
402
+ var _a;
147
403
 
148
- const menu = (0, _react2.jsx)(_core.Menu, {
149
- css: (0, _react2.css)`margin: 10px;`
150
- }, (0, _react2.jsx)(_core.MenuDivider, {
151
- title: "Quick links"
152
- }), customViews.map((cv, _) => (0, _react2.jsx)(_core.MenuItem, {
153
- key: cv.id,
154
- text: cv.label,
155
- title: cv.description,
156
- icon: cv.icon,
157
- onClick: () => spawnTab(`${_protocolRegistry.Protocols.CUSTOM_VIEW}:${cv.id}/index`)
158
- })), customViews.length > 0 ? (0, _react2.jsx)(_core.MenuDivider, null) : null, (0, _react2.jsx)(_core.MenuItem, {
159
- text: `Propose a change to version ${(_d = (_c = registerMetadata === null || registerMetadata === void 0 ? void 0 : registerMetadata.version) === null || _c === void 0 ? void 0 : _c.id) !== null && _d !== void 0 ? _d : '(missing)'}`,
160
- disabled: !canCreateCR,
161
- icon: "lightbulb",
162
- title: canCreateCR ? "A blank proposal will be created and opened in a new tab." : undefined
163
- }, (0, _react2.jsx)(_core.InputGroup, {
164
- value: newProposalIdea || undefined,
165
- placeholder: "Your idea\u2026",
166
- title: "Justification draft (you can change this later)",
167
- onChange: evt => setNewProposalIdea(evt.currentTarget.value),
168
- rightElement: (0, _react2.jsx)(_core.Button, {
169
- small: true,
170
- intent: newProposalIdea ? 'primary' : undefined,
171
- disabled: !newProposalIdea,
172
- onClick: handleNewProposal,
173
- icon: "tick"
174
- })
175
- })), (0, _react2.jsx)(_core.MenuItem, {
176
- text: "Import proposal",
177
- icon: "import",
178
- disabled: !canCreateCR,
179
- onClick: handleImportProposal
180
- }), (0, _react2.jsx)(_core.MenuItem, {
181
- text: "View register metadata",
182
- icon: "properties",
183
- onClick: () => spawnTab(_protocolRegistry.Protocols.REGISTER_META)
184
- }));
185
- const intro = (0, _react2.jsx)(_core.Callout, {
186
- intent: "primary",
187
- css: (0, _react2.css)`text-align: left;`
188
- }, stakeholder ? (0, _react2.jsx)(_react.default.Fragment, null, "You can create proposals as ", (0, _RegisterStakeholder.registerStakeholderPlain)(stakeholder), ".") : offline ? (0, _react2.jsx)(_react.default.Fragment, null, "Because this repository is offline (no remote configured), and remote username is currently required for proposal, you cannot create proposals.") : (0, _react2.jsx)(_react.default.Fragment, null, "Since your remote username is not in the list of stakeholders, you cannot create proposals currently."));
189
- const greeting = registerMetadata ? (0, _react2.jsx)(_core.NonIdealState, {
190
- title: `Welcome to ${registerMetadata.name}`,
191
- description: (0, _react2.jsx)(_react.default.Fragment, null, intro, menu)
192
- }) : registerMetadata === undefined ? (0, _react2.jsx)(_core.NonIdealState, {
193
- icon: (0, _react2.jsx)(_core.Spinner, null),
194
- description: "Loading register information\u2026"
404
+ return (0, _react2.jsx)(_util2.CardInGrid, {
405
+ css: (0, _react2.css)`
406
+ padding: 5px;
407
+ display: flex; flex-flow: column nowrap;
408
+ overflow: hidden;
409
+ transition:
410
+ width .5s linear,
411
+ height .5s linear;
412
+ `,
413
+ description: description,
414
+ className: className
415
+ }, props ? (0, _react2.jsx)(View, { ...props
416
+ }) : props === undefined ? (0, _react2.jsx)(_core.NonIdealState, {
417
+ icon: (0, _react2.jsx)(_core.Spinner, null)
195
418
  }) : (0, _react2.jsx)(_core.NonIdealState, {
196
419
  icon: "heart-broken",
197
- title: "Register metadata is missing or invalid.",
198
- description: (0, _react2.jsx)(_react.default.Fragment, null, menu)
199
- });
200
- return greeting;
201
- };
420
+ title: "Failed to load",
421
+ description: error
422
+ }), ((_a = actions === null || actions === void 0 ? void 0 : actions.length) !== null && _a !== void 0 ? _a : 0) > 0 ? (0, _react2.jsx)(_core.Menu, {
423
+ css: (0, _react2.css)`background: none !important; flex-shrink: 0;`
424
+ }, actions.map((mip, idx) => (0, _react2.jsx)(_core.MenuItem, {
425
+ key: idx,
426
+ ...mip
427
+ }))) : null);
428
+ }
202
429
 
203
- var _default = RegisterHome;
204
- exports.default = _default;
430
+ function getActionableProposalGroupsForRole(role) {
431
+ return CR_QUERIES_FOR_ROLES.filter(([, roles]) => roles.has(role));
432
+ }
433
+
434
+ const CR_BASE_QUERY = 'objPath.indexOf("/proposals/") === 0 && objPath.endsWith("main.yaml")';
435
+ const CR_QUERIES_FOR_ROLES = [['My Drafts', new Set(['submitter', 'manager', 'control-body', 'owner']), function submitterProposals(stakeholder) {
436
+ if (stakeholder && stakeholder.gitServerUsername) {
437
+ const stakeholderCondition = `obj.submittingStakeholderGitServerUsername === "${stakeholder.gitServerUsername}"`;
438
+ const query = `(obj.state === "${_cr.State.DRAFT}" || obj.state === "${_cr.State.RETURNED_FOR_CLARIFICATION}") && (${stakeholderCondition})`;
439
+ return query;
440
+ } else {
441
+ return 'false';
442
+ }
443
+ }], ['My Rejected', new Set(['submitter', 'manager', 'control-body', 'owner']), function submitterProposals(stakeholder) {
444
+ // Rejections are actionable because they can be appealed by the submitter.
445
+ if (stakeholder && stakeholder.gitServerUsername) {
446
+ const stakeholderCondition = `obj.submittingStakeholderGitServerUsername === "${stakeholder.gitServerUsername}"`;
447
+ const query = `(obj.state === "${_cr.State.REJECTED}") && (${stakeholderCondition})`;
448
+ return query;
449
+ } else {
450
+ return 'false';
451
+ }
452
+ }], ['Everyone’s Drafts or Returned', new Set(['manager', 'control-body', 'owner']), function submitterProposals(stakeholder) {
453
+ if (stakeholder && stakeholder.gitServerUsername) {
454
+ const stakeholderCondition = `obj.submittingStakeholderGitServerUsername !== "${stakeholder.gitServerUsername}"`;
455
+ const query = `(obj.state === "${_cr.State.DRAFT}" || obj.state === "${_cr.State.RETURNED_FOR_CLARIFICATION}") && (${stakeholderCondition})`;
456
+ return query;
457
+ } else {
458
+ return 'false';
459
+ }
460
+ }], // ['latest reviewed', new Set(['submitter', 'manager', 'control-body', 'owner']), function submitterProposals(stakeholder) {
461
+ // // TODO: Should filter only rejected perhaps?
462
+ // // Approved/accepted proposals can be shown in another (public) area.
463
+ // if (stakeholder && stakeholder.gitServerUsername) {
464
+ // const stakeholderCondition = stakeholder?.role !== 'submitter'
465
+ // ? 'true'
466
+ // : `obj.submittingStakeholderGitServerUsername === "${stakeholder.gitServerUsername}"`;
467
+ // // Don’t show drafts in the list of pending proposals, unless it’s user’s own drafts.
468
+ // const query = `(obj.state === "${State.ACCEPTED} || obj.state === "${State.REJECTED} || obj.state === "${State.REJECTION_UPHELD_ON_APPEAL}"") && ${stakeholderCondition}`;
469
+ // return query;
470
+ // } else {
471
+ // return 'false';
472
+ // }
473
+ // // TODO: Implement limit
474
+ // }],
475
+ // ['latest withdrawn', new Set(['submitter', 'manager', 'control-body', 'owner']), function submitterProposals(stakeholder) {
476
+ // if (stakeholder && stakeholder.gitServerUsername) {
477
+ // const stakeholderCondition = stakeholder?.role !== 'submitter'
478
+ // ? 'true'
479
+ // : `obj.submittingStakeholderGitServerUsername === "${stakeholder.gitServerUsername}"`;
480
+ // // Don’t show drafts in the list of pending proposals, unless it’s user’s own drafts.
481
+ // const query = `(obj.state === "${State.WITHDRAWN}" || obj.state === "${State.APPEAL_WITHDRAWN}") && ${stakeholderCondition}`;
482
+ // return query;
483
+ // } else {
484
+ // return 'false';
485
+ // }
486
+ // // TODO: Implement limit
487
+ // }],
488
+ ['Pending Owner Appeal Review', new Set(['owner']), function ownerProposals() {
489
+ return `obj.state === "${_cr.State.APPEALED}"`;
490
+ }], ['Pending Control Body Review', new Set(['control-body', 'owner']), function cbProposals() {
491
+ return `obj.state === "${_cr.State.SUBMITTED_FOR_CONTROL_BODY_REVIEW}"`;
492
+ }], ['Pending Manager Review', new Set(['manager', 'control-body', 'owner']), function managerProposals() {
493
+ return `obj.state === "${_cr.State.PROPOSED}"`;
494
+ }]];