@riboseinc/paneron-registry-kit 2.2.9 → 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.
- package/index.js +18 -0
- package/index.js.map +1 -1
- package/package.json +2 -2
- package/types/cr.d.ts +18 -0
- package/types/cr.js +37 -1
- package/types/cr.js.map +1 -1
- package/types/item.d.ts +1 -1
- package/types/item.js.map +1 -1
- package/types/register.js +1 -2
- package/types/register.js.map +1 -1
- package/types/stakeholder.d.ts +3 -1
- package/types/stakeholder.js +20 -0
- package/types/stakeholder.js.map +1 -1
- package/views/AnnotatedChange.js +7 -5
- package/views/AnnotatedChange.js.map +1 -1
- package/views/GenericRelatedItemView.js +4 -47
- package/views/GenericRelatedItemView.js.map +1 -1
- package/views/ItemDrawer.d.ts +11 -0
- package/views/ItemDrawer.js +69 -0
- package/views/ItemDrawer.js.map +1 -0
- package/views/change-request/ChangeRequestContext.d.ts +17 -1
- package/views/change-request/ChangeRequestContext.js +29 -5
- package/views/change-request/ChangeRequestContext.js.map +1 -1
- package/views/change-request/Proposals.d.ts +2 -0
- package/views/change-request/Proposals.js +116 -80
- package/views/change-request/Proposals.js.map +1 -1
- package/views/change-request/Summary.d.ts +12 -0
- package/views/change-request/Summary.js +59 -0
- package/views/change-request/Summary.js.map +1 -0
- package/views/change-request/TransitionHistory.d.ts +30 -0
- package/views/change-request/TransitionHistory.js +307 -0
- package/views/change-request/TransitionHistory.js.map +1 -0
- package/views/change-request/TransitionOptions.d.ts +38 -0
- package/views/{detail/ChangeRequest/transitions.js → change-request/TransitionOptions.js} +61 -51
- package/views/change-request/TransitionOptions.js.map +1 -0
- package/views/change-request/objectChangeset.d.ts +1 -1
- package/views/change-request/objectChangeset.js +1 -1
- package/views/change-request/objectChangeset.js.map +1 -1
- package/views/detail/ChangeRequest/index.js +129 -142
- package/views/detail/ChangeRequest/index.js.map +1 -1
- package/views/detail/RegisterHome/MetaSummary.d.ts +9 -0
- package/views/detail/RegisterHome/MetaSummary.js +35 -0
- package/views/detail/RegisterHome/MetaSummary.js.map +1 -0
- package/views/detail/RegisterHome/Proposal.d.ts +24 -0
- package/views/detail/RegisterHome/Proposal.js +228 -0
- package/views/detail/RegisterHome/Proposal.js.map +1 -0
- package/views/detail/RegisterHome/index.js +427 -137
- package/views/detail/RegisterHome/index.js.map +1 -1
- package/views/detail/RegisterItem/index.d.ts +2 -3
- package/views/detail/RegisterItem/index.js +239 -140
- package/views/detail/RegisterItem/index.js.map +1 -1
- package/views/detail/RegisterMeta/RegisterMetaForm.js +37 -45
- package/views/detail/RegisterMeta/RegisterMetaForm.js.map +1 -1
- package/views/detail/RegisterMeta/index.js +14 -11
- package/views/detail/RegisterMeta/index.js.map +1 -1
- package/views/diffing/InlineDiff.d.ts +27 -1
- package/views/diffing/InlineDiff.js +113 -2
- package/views/diffing/InlineDiff.js.map +1 -1
- package/views/util.d.ts +36 -2
- package/views/util.js +203 -2
- package/views/util.js.map +1 -1
- package/views/detail/ChangeRequest/transitions.d.ts +0 -28
- 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 =
|
|
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
|
|
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
|
|
36
|
+
var _MetaSummary = _interopRequireDefault(require("./MetaSummary"));
|
|
29
37
|
|
|
30
|
-
|
|
38
|
+
var _util2 = require("../../util");
|
|
31
39
|
|
|
32
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
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
|
-
|
|
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
|
-
|
|
77
|
-
|
|
78
|
-
|
|
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
|
-
|
|
85
|
-
|
|
86
|
-
|
|
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
|
-
|
|
90
|
-
|
|
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
|
-
|
|
122
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
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
|
-
|
|
149
|
-
css: (0, _react2.css)`
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
icon:
|
|
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: "
|
|
198
|
-
description:
|
|
199
|
-
})
|
|
200
|
-
|
|
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
|
-
|
|
204
|
-
|
|
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
|
+
}]];
|