@riboseinc/paneron-registry-kit 2.2.30 → 2.2.32

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 (74) hide show
  1. package/index.js +1 -0
  2. package/index.js.map +1 -1
  3. package/item-classes/Tree.d.ts +5 -0
  4. package/item-classes/Tree.js +115 -0
  5. package/item-classes/Tree.js.map +1 -0
  6. package/item-classes/treeNodes.d.ts +12 -0
  7. package/item-classes/treeNodes.js +68 -0
  8. package/item-classes/treeNodes.js.map +1 -0
  9. package/package.json +2 -2
  10. package/proposals/actionableGroups/Tree.d.ts +7 -0
  11. package/proposals/actionableGroups/Tree.js +179 -0
  12. package/proposals/actionableGroups/Tree.js.map +1 -0
  13. package/proposals/actionableGroups/queries.d.ts +5 -0
  14. package/proposals/actionableGroups/queries.js +81 -0
  15. package/proposals/actionableGroups/queries.js.map +1 -0
  16. package/proposals/actionableGroups/treeNodes.d.ts +26 -0
  17. package/proposals/actionableGroups/treeNodes.js +96 -0
  18. package/proposals/actionableGroups/treeNodes.js.map +1 -0
  19. package/proposals/actionableGroups/types.d.ts +6 -0
  20. package/proposals/actionableGroups/types.js +5 -0
  21. package/proposals/actionableGroups/types.js.map +1 -0
  22. package/types/cr.d.ts +1 -0
  23. package/types/cr.js.map +1 -1
  24. package/types/register.d.ts +4 -1
  25. package/types/register.js.map +1 -1
  26. package/types/stakeholder.d.ts +22 -41
  27. package/types/stakeholder.js +34 -16
  28. package/types/stakeholder.js.map +1 -1
  29. package/types/views.d.ts +2 -0
  30. package/types/views.js.map +1 -1
  31. package/views/BrowserCtx.d.ts +1 -1
  32. package/views/BrowserCtx.js.map +1 -1
  33. package/views/GenericRelatedItemView.js +21 -8
  34. package/views/GenericRelatedItemView.js.map +1 -1
  35. package/views/ItemDetailsDrawer.d.ts +1 -0
  36. package/views/ItemDetailsDrawer.js +4 -2
  37. package/views/ItemDetailsDrawer.js.map +1 -1
  38. package/views/ItemSearchDrawer.js +1 -1
  39. package/views/ItemSearchDrawer.js.map +1 -1
  40. package/views/RegisterStakeholder.js +2 -2
  41. package/views/RegisterStakeholder.js.map +1 -1
  42. package/views/StatefulTree.d.ts +28 -0
  43. package/views/StatefulTree.js +131 -0
  44. package/views/StatefulTree.js.map +1 -0
  45. package/views/change-request/TransitionHistory.js +6 -3
  46. package/views/change-request/TransitionHistory.js.map +1 -1
  47. package/views/change-request/TransitionOptions.js +37 -13
  48. package/views/change-request/TransitionOptions.js.map +1 -1
  49. package/views/detail/RegisterHome/index.js +20 -79
  50. package/views/detail/RegisterHome/index.js.map +1 -1
  51. package/views/detail/RegisterItem/index.d.ts +2 -2
  52. package/views/detail/RegisterItem/index.js +7 -2
  53. package/views/detail/RegisterItem/index.js.map +1 -1
  54. package/views/detail/RegisterItemClass.d.ts +12 -0
  55. package/views/detail/RegisterItemClass.js +98 -0
  56. package/views/detail/RegisterItemClass.js.map +1 -0
  57. package/views/detail/RegisterMeta/RegisterMetaForm.js +272 -114
  58. package/views/detail/RegisterMeta/RegisterMetaForm.js.map +1 -1
  59. package/views/detail/RegisterMeta/index.js +1 -1
  60. package/views/detail/RegisterMeta/index.js.map +1 -1
  61. package/views/index.js +63 -6
  62. package/views/index.js.map +1 -1
  63. package/views/protocolRegistry.d.ts +1 -0
  64. package/views/protocolRegistry.js +4 -0
  65. package/views/protocolRegistry.js.map +1 -1
  66. package/views/sidebar/Browse/index.js +8 -44
  67. package/views/sidebar/Browse/index.js.map +1 -1
  68. package/views/sidebar/Registration/index.js.map +1 -1
  69. package/views/sidebar/index.d.ts +2 -1
  70. package/views/sidebar/index.js +77 -62
  71. package/views/sidebar/index.js.map +1 -1
  72. package/views/util.d.ts +5 -0
  73. package/views/util.js +42 -4
  74. package/views/util.js.map +1 -1
package/index.js CHANGED
@@ -139,6 +139,7 @@ const makeRegistryExtension = function (opts) {
139
139
  const mainView = function _RegistryView() {
140
140
  return _react.default.createElement(_views.RegistryView, {
141
141
  itemClassConfiguration: opts.itemClassConfiguration,
142
+ itemClassGroups: opts.itemClassGroups,
142
143
  subregisters: opts.subregisters,
143
144
  CustomWorkspace: opts.CustomWorkspace,
144
145
  defaultSearchCriteria: opts.defaultSearchCriteria,
package/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,aAAa,EAAE,MAAM,kCAAkC,CAAC;AAEjE,OAAO,aAAa,MAAM,wDAAwD,CAAC;AAInF,OAAO,kBAAkB,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAQvC,MAAM,CAAC,MAAM,qBAAqB,GAA2B,UAAU,IAAI;IACzE,MAAM,EAAE,IAAI,EAAE,GAAG,IAAI,CAAC;IAEtB,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,sBAAsB,CAAC,EAAE;QAC5D,KAAK,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE;YACtD,MAAM,IAAI,GAAG,IAAW,CAAC;YACzB,IAAI,IAAI,EAAE;gBACR,GAAG,CAAC,KAAK,CAAC,MAAoD,CAAC,GAAG,SAAS,uBAAuB,CAAC,KAAK;oBACtG,OAAO,CACL,oBAAC,aAAa,IACV,QAAQ,EAAE,mBAAmB,GAAG,CAAC,IAAI,CAAC,KAAK,EAAE,EAC7C,MAAM,EAAE,MAAM,KAAK,cAAc;wBACnC,oBAAC,IAAI,OAAK,KAAK,GAAI,CACL,CACjB,CAAC;gBACJ,CAAC,CAAC;aACH;SACF;KACF;IAED,MAAM,QAAQ,GAAoC,SAAS,aAAa;QACtE,OAAO,CACL,oBAAC,YAAY,IACX,sBAAsB,EAAE,IAAI,CAAC,sBAAsB,EACnD,YAAY,EAAE,IAAI,CAAC,YAAY,EAC/B,eAAe,EAAE,IAAI,CAAC,eAAe,EACrC,qBAAqB,EAAE,IAAI,CAAC,qBAAqB,EACjD,aAAa,EAAE,IAAI,CAAC,aAAa,EACjC,uBAAuB,EAAE,IAAI,CAAC,uBAAuB,EACrD,eAAe,EAAE,IAAI,CAAC,eAAe,GACrC,CACH,CAAC;IACJ,CAAC,CAAC;IAEF,OAAO,aAAa,CAAC;QACnB,QAAQ;QACR,IAAI;QACJ,sBAAsB,EAAE,OAAO;QAC/B,iBAAiB,EAAE,EAAE;QACrB,kBAAkB;KACnB,CAAC,CAAC;AACL,CAAC,CAAC;AAGF,aAAa;AAEb,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,iCAAiC,EAAE,MAAM,uBAAuB,CAAC;AAC9H,OAAO,sBAAsB,MAAM,gCAAgC,CAAC;AACpE,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,sBAAsB,MAAM,+CAA+C,CAAC;AACnF,OAAO,yBAAyB,MAAM,yCAAyC,CAAC;AAChF,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAE9C,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AACrD,OAAO,EAAE,oBAAoB,EAAE,MAAM,6CAA6C,CAAC;AACnF,OAAO,YAAY,MAAM,6BAA6B,CAAC;AAEvD,OAAO,EACL,iBAAiB,EACjB,iBAAiB,EACjB,YAAY,EACZ,iCAAiC,EACjC,UAAU,EACV,sBAAsB,EACtB,sBAAsB,EACtB,kBAAkB,EAClB,yBAAyB,EACzB,UAAU,EAEV,SAAS,EACT,oBAAoB,EACpB,YAAY,GACb,CAAC","sourcesContent":["import React from 'react';\nimport { makeExtension } from '@riboseinc/paneron-extension-kit';\nimport type { Extension } from '@riboseinc/paneron-extension-kit/types';\nimport ErrorBoundary from '@riboseinc/paneron-extension-kit/widgets/ErrorBoundary';\nimport type { ExtensionMakerProps } from '@riboseinc/paneron-extension-kit/types/extension-maker';\nimport type { RegistryViewProps } from './types';\nimport type { ItemClassConfiguration } from './types/views';\nimport datasetInitializer from './migrations/initial';\nimport { RegistryView } from './views';\n\nexport type RegistryExtensionMakerProps =\n Pick<ExtensionMakerProps, 'name'> & RegistryViewProps\n\nexport type RegistryExtensionMaker =\n (opts: RegistryExtensionMakerProps) => Promise<Extension>;\n\nexport const makeRegistryExtension: RegistryExtensionMaker = function (opts) {\n const { name } = opts;\n\n for (const cls of Object.values(opts.itemClassConfiguration)) {\n for (const [viewID, view] of Object.entries(cls.views)) {\n const View = view as any;\n if (View) {\n cls.views[viewID as keyof ItemClassConfiguration<any>[\"views\"]] = function WrappedRegisterItemView(props) {\n return (\n <ErrorBoundary\n viewName={`Detail view for ${cls.meta.title}`}\n inline={viewID === 'listItemView'}>\n <View {...props} />\n </ErrorBoundary>\n );\n };\n }\n }\n }\n\n const mainView: ExtensionMakerProps[\"mainView\"] = function _RegistryView () {\n return (\n <RegistryView\n itemClassConfiguration={opts.itemClassConfiguration}\n subregisters={opts.subregisters}\n CustomWorkspace={opts.CustomWorkspace}\n defaultSearchCriteria={opts.defaultSearchCriteria}\n keyExpression={opts.keyExpression}\n getQuickSearchPredicate={opts.getQuickSearchPredicate}\n alterApprovedCR={opts.alterApprovedCR}\n />\n );\n };\n\n return makeExtension({\n mainView,\n name,\n requiredHostAppVersion: '2.0.0',\n datasetMigrations: {},\n datasetInitializer,\n });\n};\n\n\n// Re-exports\n\nimport { BrowserCtx } from './views/BrowserCtx';\nimport { itemPathInCR, itemPathToItemRef, itemRefToItemPath, incompleteItemRefToItemPathPrefix } from './views/itemPathUtils';\nimport GenericRelatedItemView from './views/GenericRelatedItemView';\nimport { PropertyDetailView } from './views/util';\nimport CRITERIA_CONFIGURATION from './views/FilterCriteria/CRITERIA_CONFIGURATION';\nimport useSingleRegisterItemData from './views/hooks/useSingleRegisterItemData';\nimport { isAddition } from './types/proposal';\nimport type { Payload } from './types/item';\nimport { Protocols } from './views/protocolRegistry';\nimport { ChangeRequestContext } from './views/change-request/ChangeRequestContext';\nimport RegisterHome from './views/detail/RegisterHome';\n\nexport {\n itemRefToItemPath,\n itemPathToItemRef,\n itemPathInCR,\n incompleteItemRefToItemPathPrefix,\n BrowserCtx,\n CRITERIA_CONFIGURATION,\n GenericRelatedItemView,\n PropertyDetailView,\n useSingleRegisterItemData,\n isAddition,\n Payload,\n Protocols,\n ChangeRequestContext,\n RegisterHome,\n};\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,aAAa,EAAE,MAAM,kCAAkC,CAAC;AAEjE,OAAO,aAAa,MAAM,wDAAwD,CAAC;AAInF,OAAO,kBAAkB,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAQvC,MAAM,CAAC,MAAM,qBAAqB,GAA2B,UAAU,IAAI;IACzE,MAAM,EAAE,IAAI,EAAE,GAAG,IAAI,CAAC;IAEtB,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,sBAAsB,CAAC,EAAE;QAC5D,KAAK,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE;YACtD,MAAM,IAAI,GAAG,IAAW,CAAC;YACzB,IAAI,IAAI,EAAE;gBACR,GAAG,CAAC,KAAK,CAAC,MAAoD,CAAC,GAAG,SAAS,uBAAuB,CAAC,KAAK;oBACtG,OAAO,CACL,oBAAC,aAAa,IACV,QAAQ,EAAE,mBAAmB,GAAG,CAAC,IAAI,CAAC,KAAK,EAAE,EAC7C,MAAM,EAAE,MAAM,KAAK,cAAc;wBACnC,oBAAC,IAAI,OAAK,KAAK,GAAI,CACL,CACjB,CAAC;gBACJ,CAAC,CAAC;aACH;SACF;KACF;IAED,MAAM,QAAQ,GAAoC,SAAS,aAAa;QACtE,OAAO,CACL,oBAAC,YAAY,IACX,sBAAsB,EAAE,IAAI,CAAC,sBAAsB,EACnD,eAAe,EAAE,IAAI,CAAC,eAAe,EACrC,YAAY,EAAE,IAAI,CAAC,YAAY,EAC/B,eAAe,EAAE,IAAI,CAAC,eAAe,EACrC,qBAAqB,EAAE,IAAI,CAAC,qBAAqB,EACjD,aAAa,EAAE,IAAI,CAAC,aAAa,EACjC,uBAAuB,EAAE,IAAI,CAAC,uBAAuB,EACrD,eAAe,EAAE,IAAI,CAAC,eAAe,GACrC,CACH,CAAC;IACJ,CAAC,CAAC;IAEF,OAAO,aAAa,CAAC;QACnB,QAAQ;QACR,IAAI;QACJ,sBAAsB,EAAE,OAAO;QAC/B,iBAAiB,EAAE,EAAE;QACrB,kBAAkB;KACnB,CAAC,CAAC;AACL,CAAC,CAAC;AAGF,aAAa;AAEb,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,iCAAiC,EAAE,MAAM,uBAAuB,CAAC;AAC9H,OAAO,sBAAsB,MAAM,gCAAgC,CAAC;AACpE,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,sBAAsB,MAAM,+CAA+C,CAAC;AACnF,OAAO,yBAAyB,MAAM,yCAAyC,CAAC;AAChF,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAE9C,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AACrD,OAAO,EAAE,oBAAoB,EAAE,MAAM,6CAA6C,CAAC;AACnF,OAAO,YAAY,MAAM,6BAA6B,CAAC;AAEvD,OAAO,EACL,iBAAiB,EACjB,iBAAiB,EACjB,YAAY,EACZ,iCAAiC,EACjC,UAAU,EACV,sBAAsB,EACtB,sBAAsB,EACtB,kBAAkB,EAClB,yBAAyB,EACzB,UAAU,EAEV,SAAS,EACT,oBAAoB,EACpB,YAAY,GACb,CAAC","sourcesContent":["import React from 'react';\nimport { makeExtension } from '@riboseinc/paneron-extension-kit';\nimport type { Extension } from '@riboseinc/paneron-extension-kit/types';\nimport ErrorBoundary from '@riboseinc/paneron-extension-kit/widgets/ErrorBoundary';\nimport type { ExtensionMakerProps } from '@riboseinc/paneron-extension-kit/types/extension-maker';\nimport type { RegistryViewProps } from './types';\nimport type { ItemClassConfiguration } from './types/views';\nimport datasetInitializer from './migrations/initial';\nimport { RegistryView } from './views';\n\nexport type RegistryExtensionMakerProps =\n Pick<ExtensionMakerProps, 'name'> & RegistryViewProps\n\nexport type RegistryExtensionMaker =\n (opts: RegistryExtensionMakerProps) => Promise<Extension>;\n\nexport const makeRegistryExtension: RegistryExtensionMaker = function (opts) {\n const { name } = opts;\n\n for (const cls of Object.values(opts.itemClassConfiguration)) {\n for (const [viewID, view] of Object.entries(cls.views)) {\n const View = view as any;\n if (View) {\n cls.views[viewID as keyof ItemClassConfiguration<any>[\"views\"]] = function WrappedRegisterItemView(props) {\n return (\n <ErrorBoundary\n viewName={`Detail view for ${cls.meta.title}`}\n inline={viewID === 'listItemView'}>\n <View {...props} />\n </ErrorBoundary>\n );\n };\n }\n }\n }\n\n const mainView: ExtensionMakerProps[\"mainView\"] = function _RegistryView () {\n return (\n <RegistryView\n itemClassConfiguration={opts.itemClassConfiguration}\n itemClassGroups={opts.itemClassGroups}\n subregisters={opts.subregisters}\n CustomWorkspace={opts.CustomWorkspace}\n defaultSearchCriteria={opts.defaultSearchCriteria}\n keyExpression={opts.keyExpression}\n getQuickSearchPredicate={opts.getQuickSearchPredicate}\n alterApprovedCR={opts.alterApprovedCR}\n />\n );\n };\n\n return makeExtension({\n mainView,\n name,\n requiredHostAppVersion: '2.0.0',\n datasetMigrations: {},\n datasetInitializer,\n });\n};\n\n\n// Re-exports\n\nimport { BrowserCtx } from './views/BrowserCtx';\nimport { itemPathInCR, itemPathToItemRef, itemRefToItemPath, incompleteItemRefToItemPathPrefix } from './views/itemPathUtils';\nimport GenericRelatedItemView from './views/GenericRelatedItemView';\nimport { PropertyDetailView } from './views/util';\nimport CRITERIA_CONFIGURATION from './views/FilterCriteria/CRITERIA_CONFIGURATION';\nimport useSingleRegisterItemData from './views/hooks/useSingleRegisterItemData';\nimport { isAddition } from './types/proposal';\nimport type { Payload } from './types/item';\nimport { Protocols } from './views/protocolRegistry';\nimport { ChangeRequestContext } from './views/change-request/ChangeRequestContext';\nimport RegisterHome from './views/detail/RegisterHome';\n\nexport {\n itemRefToItemPath,\n itemPathToItemRef,\n itemPathInCR,\n incompleteItemRefToItemPathPrefix,\n BrowserCtx,\n CRITERIA_CONFIGURATION,\n GenericRelatedItemView,\n PropertyDetailView,\n useSingleRegisterItemData,\n isAddition,\n Payload,\n Protocols,\n ChangeRequestContext,\n RegisterHome,\n};\n"]}
@@ -0,0 +1,5 @@
1
+ /** @jsx jsx */
2
+ /** @jsxFrag React.Fragment */
3
+ import React from 'react';
4
+ declare const ItemClassTree: React.VoidFunctionComponent<Record<never, never>>;
5
+ export default ItemClassTree;
@@ -0,0 +1,115 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+
8
+ var _react = require("react");
9
+
10
+ var _react2 = require("@emotion/react");
11
+
12
+ var _context = require("@riboseinc/paneron-extension-kit/context");
13
+
14
+ var _context2 = require("@riboseinc/paneron-extension-kit/widgets/TabbedWorkspace/context");
15
+
16
+ var _StatefulTree = _interopRequireDefault(require("../views/StatefulTree"));
17
+
18
+ var _ChangeRequestContext = require("../views/change-request/ChangeRequestContext");
19
+
20
+ var _objectChangeset = require("../views/change-request/objectChangeset");
21
+
22
+ var _BrowserCtx = require("../views/BrowserCtx");
23
+
24
+ var _itemPathUtils = require("../views/itemPathUtils");
25
+
26
+ var _protocolRegistry = require("../views/protocolRegistry");
27
+
28
+ var _treeNodes = require("./treeNodes");
29
+
30
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
31
+
32
+ /** @jsx jsx */
33
+
34
+ /** @jsxFrag React.Fragment */
35
+ const ItemClassTree = function () {
36
+ const {
37
+ performOperation,
38
+ updateObjects,
39
+ makeRandomID
40
+ } = (0, _react.useContext)(_context.DatasetContext);
41
+ const {
42
+ spawnTab
43
+ } = (0, _react.useContext)(_context2.TabbedWorkspaceContext);
44
+ const {
45
+ changeRequest: activeCR,
46
+ canEdit: activeCRIsEditable
47
+ } = (0, _react.useContext)(_ChangeRequestContext.ChangeRequestContext);
48
+ const {
49
+ subregisters,
50
+ itemClasses,
51
+ itemClassGroups
52
+ } = (0, _react.useContext)(_BrowserCtx.BrowserCtx);
53
+ const createItem = (0, _react.useCallback)(async function _createItem(classID, subregisterID) {
54
+ var _a;
55
+
56
+ if (!updateObjects || !makeRandomID || !activeCRIsEditable || !activeCR) {
57
+ throw new Error("Unable to create item: likely current proposal is not editable or dataset is read-only");
58
+ }
59
+
60
+ if (subregisters && !subregisterID) {
61
+ throw new Error("Unable to create item: register uses subregisters, but subregister ID was not provided");
62
+ }
63
+
64
+ const clsConfig = itemClasses[classID];
65
+
66
+ if (!clsConfig) {
67
+ throw new Error("Unable to generate new item data: item class configuration is missing");
68
+ }
69
+
70
+ const initialItemData = (_a = clsConfig === null || clsConfig === void 0 ? void 0 : clsConfig.defaults) !== null && _a !== void 0 ? _a : {};
71
+ const itemID = await makeRandomID();
72
+ const ref = {
73
+ classID,
74
+ itemID,
75
+ subregisterID
76
+ };
77
+ const registerItem = {
78
+ id: itemID,
79
+ dateAccepted: new Date(),
80
+ status: 'valid',
81
+ data: initialItemData
82
+ };
83
+ const itemPath = (0, _itemPathUtils.itemRefToItemPath)(ref);
84
+ await updateObjects({
85
+ commitMessage: `propose to add new ${ref.classID}`,
86
+ objectChangeset: (0, _objectChangeset.updateCRObjectChangeset)(activeCR, {
87
+ [itemPath]: {
88
+ type: 'addition'
89
+ }
90
+ }, {
91
+ [itemPath]: registerItem
92
+ }),
93
+ _dangerouslySkipValidation: true
94
+ });
95
+ spawnTab(`${_protocolRegistry.Protocols.ITEM_DETAILS}:${(0, _itemPathUtils.itemRefToItemPath)(ref, activeCR.id)}`);
96
+ }, [activeCR, activeCRIsEditable, subregisters === undefined, spawnTab, updateObjects, makeRandomID]);
97
+ const handleAdd = (0, _react.useMemo)(() => !subregisters && activeCRIsEditable && performOperation ? clsID => performOperation('generating new item', createItem)(clsID) : undefined, [createItem, subregisters === undefined, activeCRIsEditable, performOperation]);
98
+ const getNodes = (0, _react.useCallback)(state => {
99
+ var _a;
100
+
101
+ return (0, _treeNodes.getMaybeGroupedItemClassesAsTreeNodes)(itemClasses, itemClassGroups, {
102
+ selectedItemID: (_a = state.selectedItemID) !== null && _a !== void 0 ? _a : undefined,
103
+ expandedGroupLabels: new Set(state.expandedItemIDs),
104
+ onProposeItem: handleAdd
105
+ });
106
+ }, [itemClasses, itemClassGroups, handleAdd]);
107
+ return (0, _react2.jsx)(_StatefulTree.default, {
108
+ getNodes: getNodes,
109
+ stateKey: "item-browser",
110
+ onItemDoubleClick: node => spawnTab(`${_protocolRegistry.Protocols.ITEM_CLASS}:${node.id}`)
111
+ });
112
+ };
113
+
114
+ var _default = ItemClassTree;
115
+ exports.default = _default;
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Tree.js","sourceRoot":"","sources":["../../src/item-classes/Tree.tsx"],"names":[],"mappings":"AAAA,eAAe;AACf,8BAA8B;AAE9B,OAAc,EAAE,UAAU,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AAChE,OAAO,EAAE,GAAG,EAAE,MAAM,gBAAgB,CAAC;AAErC,OAAO,EAAE,cAAc,EAAE,MAAM,0CAA0C,CAAC;AAC1E,OAAO,EAAE,sBAAsB,EAAE,MAAM,kEAAkE,CAAC;AAE1G,OAAO,mBAAgD,MAAM,uBAAuB,CAAC;AACrF,OAAO,EAAE,oBAAoB,EAAE,MAAM,8CAA8C,CAAC;AACpF,OAAO,EAAE,uBAAuB,EAAE,MAAM,yCAAyC,CAAC;AAClF,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEjD,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AAEtD,OAAO,EAAE,qCAAqC,EAAE,MAAM,aAAa,CAAC;AAGpE,MAAM,aAAa,GAAsD;IAEvE,MAAM,EAAE,gBAAgB,EAAE,aAAa,EAAE,YAAY,EAAE,GAAG,UAAU,CAAC,cAAc,CAAC,CAAC;IACrF,MAAM,EAAE,QAAQ,EAAE,GAAG,UAAU,CAAC,sBAAsB,CAAC,CAAC;IACxD,MAAM,EAAE,aAAa,EAAE,QAAQ,EAAE,OAAO,EAAE,kBAAkB,EAAE,GAAG,UAAU,CAAC,oBAAoB,CAAC,CAAC;IAClG,MAAM,EAAE,YAAY,EAAE,WAAW,EAAE,eAAe,EAAE,GAAG,UAAU,CAAC,UAAU,CAAC,CAAC;IAE9E,MAAM,UAAU,GAAG,WAAW,CAAC,KAAK,UAAU,WAAW,CAAC,OAAe,EAAE,aAAsB;;QAC/F,IAAI,CAAC,aAAa,IAAI,CAAC,YAAY,IAAI,CAAC,kBAAkB,IAAI,CAAC,QAAQ,EAAE;YACvE,MAAM,IAAI,KAAK,CAAC,wFAAwF,CAAC,CAAC;SAC3G;QACD,IAAI,YAAY,IAAI,CAAC,aAAa,EAAE;YAClC,MAAM,IAAI,KAAK,CAAC,wFAAwF,CAAC,CAAC;SAC3G;QACD,MAAM,SAAS,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC;QACvC,IAAI,CAAC,SAAS,EAAE;YACd,MAAM,IAAI,KAAK,CAAC,uEAAuE,CAAC,CAAC;SAC1F;QACD,MAAM,eAAe,GAAG,MAAA,SAAS,aAAT,SAAS,uBAAT,SAAS,CAAE,QAAQ,mCAAI,EAAE,CAAC;QAClD,MAAM,MAAM,GAAG,MAAM,YAAY,EAAE,CAAC;QACpC,MAAM,GAAG,GAA0B,EAAE,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,CAAC;QACtE,MAAM,YAAY,GAAsB;YACtC,EAAE,EAAE,MAAM;YACV,YAAY,EAAE,IAAI,IAAI,EAAE;YACxB,MAAM,EAAE,OAAO;YACf,IAAI,EAAE,eAAe;SACtB,CAAC;QACF,MAAM,QAAQ,GAAG,iBAAiB,CAAC,GAAG,CAAC,CAAC;QACxC,MAAM,aAAa,CAAC;YAClB,aAAa,EAAE,sBAAsB,GAAG,CAAC,OAAO,EAAE;YAClD,eAAe,EAAE,uBAAuB,CACtC,QAAe,EACf,EAAE,CAAC,QAAQ,CAAC,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,EACpC,EAAE,CAAC,QAAQ,CAAC,EAAE,YAAY,EAAE,CAC7B;YACD,0BAA0B,EAAE,IAAI;SACjC,CAAC,CAAC;QACH,QAAQ,CAAC,GAAG,SAAS,CAAC,YAAY,IAAI,iBAAiB,CAAC,GAAG,EAAE,QAAQ,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;IAC/E,CAAC,EAAE,CAAC,QAAQ,EAAE,kBAAkB,EAAE,YAAY,KAAK,SAAS,EAAE,QAAQ,EAAE,aAAa,EAAE,YAAY,CAAC,CAAC,CAAC;IAEtG,MAAM,SAAS,GAAmD,OAAO,CAAC,CAAC,GAAG,EAAE,CAC9E,CAAC,YAAY,IAAI,kBAAkB,IAAI,gBAAgB;QACrD,CAAC,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,gBAAgB,CAAC,qBAAqB,EAAE,UAAU,CAAC,CAAC,KAAK,CAAC;QACvE,CAAC,CAAC,SAAS,CACd,EAAE,CAAC,UAAU,EAAE,YAAY,KAAK,SAAS,EAAE,kBAAkB,EAAE,gBAAgB,CAAC,CAAC,CAAC;IAEnF,MAAM,QAAQ,GAAG,WAAW,CAC1B,CAAC,CAAC,KAAgB,EAAE,EAAE;;QACpB,OAAA,qCAAqC,CAAC,WAAW,EAAE,eAAe,EAAE;YAClE,cAAc,EAAE,MAAA,KAAK,CAAC,cAAc,mCAAI,SAAS;YACjD,mBAAmB,EAAE,IAAI,GAAG,CAAC,KAAK,CAAC,eAAe,CAAC;YACnD,aAAa,EAAE,SAAS;SACzB,CAAC,CAAA;KAAA,CAAC,EACL,CAAC,WAAW,EAAE,eAAe,EAAE,SAAS,CAAC,CAC1C,CAAC;IAEF,OAAO,IAAC,mBAAmB,IACzB,QAAQ,EAAE,QAAQ,EAClB,QAAQ,EAAC,cAAc,EACvB,iBAAiB,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,QAAQ,CAAC,GAAG,SAAS,CAAC,UAAU,IAAI,IAAI,CAAC,EAAE,EAAE,CAAC,GAC3E,CAAC;AACL,CAAC,CAAC;AAGF,eAAe,aAAa,CAAC","sourcesContent":["/** @jsx jsx */\n/** @jsxFrag React.Fragment */\n\nimport React, { useContext, useMemo, useCallback } from 'react';\nimport { jsx } from '@emotion/react';\n\nimport { DatasetContext } from '@riboseinc/paneron-extension-kit/context';\nimport { TabbedWorkspaceContext } from '@riboseinc/paneron-extension-kit/widgets/TabbedWorkspace/context';\n\nimport GenericStatefulTree, { type State as TreeState } from '../views/StatefulTree';\nimport { ChangeRequestContext } from '../views/change-request/ChangeRequestContext';\nimport { updateCRObjectChangeset } from '../views/change-request/objectChangeset';\nimport { BrowserCtx } from '../views/BrowserCtx';\nimport type { RegisterItem, InternalItemReference } from '../types';\nimport { itemRefToItemPath } from '../views/itemPathUtils';\nimport { Protocols } from '../views/protocolRegistry';\n\nimport { getMaybeGroupedItemClassesAsTreeNodes } from './treeNodes';\n\n\nconst ItemClassTree: React.VoidFunctionComponent<Record<never, never>> = function () {\n\n const { performOperation, updateObjects, makeRandomID } = useContext(DatasetContext);\n const { spawnTab } = useContext(TabbedWorkspaceContext);\n const { changeRequest: activeCR, canEdit: activeCRIsEditable } = useContext(ChangeRequestContext);\n const { subregisters, itemClasses, itemClassGroups } = useContext(BrowserCtx);\n\n const createItem = useCallback(async function _createItem(classID: string, subregisterID?: string) {\n if (!updateObjects || !makeRandomID || !activeCRIsEditable || !activeCR) {\n throw new Error(\"Unable to create item: likely current proposal is not editable or dataset is read-only\");\n }\n if (subregisters && !subregisterID) {\n throw new Error(\"Unable to create item: register uses subregisters, but subregister ID was not provided\");\n }\n const clsConfig = itemClasses[classID];\n if (!clsConfig) {\n throw new Error(\"Unable to generate new item data: item class configuration is missing\");\n }\n const initialItemData = clsConfig?.defaults ?? {};\n const itemID = await makeRandomID();\n const ref: InternalItemReference = { classID, itemID, subregisterID };\n const registerItem: RegisterItem<any> = {\n id: itemID,\n dateAccepted: new Date(),\n status: 'valid',\n data: initialItemData,\n };\n const itemPath = itemRefToItemPath(ref);\n await updateObjects({\n commitMessage: `propose to add new ${ref.classID}`,\n objectChangeset: updateCRObjectChangeset(\n activeCR as any,\n { [itemPath]: { type: 'addition' } },\n { [itemPath]: registerItem },\n ),\n _dangerouslySkipValidation: true,\n });\n spawnTab(`${Protocols.ITEM_DETAILS}:${itemRefToItemPath(ref, activeCR.id)}`);\n }, [activeCR, activeCRIsEditable, subregisters === undefined, spawnTab, updateObjects, makeRandomID]);\n\n const handleAdd: undefined | ((clsID: string) => Promise<void>) = useMemo((() =>\n !subregisters && activeCRIsEditable && performOperation\n ? (clsID) => performOperation('generating new item', createItem)(clsID)\n : undefined\n ), [createItem, subregisters === undefined, activeCRIsEditable, performOperation]);\n\n const getNodes = useCallback(\n ((state: TreeState) =>\n getMaybeGroupedItemClassesAsTreeNodes(itemClasses, itemClassGroups, {\n selectedItemID: state.selectedItemID ?? undefined,\n expandedGroupLabels: new Set(state.expandedItemIDs),\n onProposeItem: handleAdd,\n })),\n [itemClasses, itemClassGroups, handleAdd],\n );\n\n return <GenericStatefulTree\n getNodes={getNodes}\n stateKey=\"item-browser\"\n onItemDoubleClick={(node) => spawnTab(`${Protocols.ITEM_CLASS}:${node.id}`)}\n />;\n};\n\n\nexport default ItemClassTree;\n"]}
@@ -0,0 +1,12 @@
1
+ /** @jsx jsx */
2
+ /** @jsxFrag React.Fragment */
3
+ import type { RegistryViewProps } from '../types/views';
4
+ import type { TreeNodeInfo } from '@blueprintjs/core';
5
+ export declare type ItemOrGroupTreeNode = TreeNodeInfo<{
6
+ type: 'group' | 'item';
7
+ }>;
8
+ export declare function getMaybeGroupedItemClassesAsTreeNodes<T extends RegistryViewProps>(itemClasses: T['itemClassConfiguration'], itemClassGroups: T['itemClassGroups'] | undefined, opts?: {
9
+ expandedGroupLabels?: Set<string>;
10
+ selectedItemID?: string;
11
+ onProposeItem?: (clsID: string) => Promise<void>;
12
+ }): ItemOrGroupTreeNode[];
@@ -0,0 +1,68 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.getMaybeGroupedItemClassesAsTreeNodes = getMaybeGroupedItemClassesAsTreeNodes;
7
+
8
+ var _react = require("@emotion/react");
9
+
10
+ var _util = require("../views/util");
11
+
12
+ /** @jsx jsx */
13
+
14
+ /** @jsxFrag React.Fragment */
15
+
16
+ /**
17
+ * Tools for rendering proposal groups as tree nodes.
18
+ * Each proposal group is top-level node, with proposals as nested nodes.
19
+ */
20
+ //import React, { useContext, useMemo } from 'react';
21
+ function getMaybeGroupedItemClassesAsTreeNodes(itemClasses, itemClassGroups, opts) {
22
+ if (!itemClassGroups) {
23
+ return getItemClassesAsTreeNodes(itemClasses, Object.keys(itemClasses), opts);
24
+ } else {
25
+ return Object.entries(itemClassGroups).map(([groupLabel, clsIDs]) => {
26
+ var _a;
27
+
28
+ const hasSelectedClass = (opts === null || opts === void 0 ? void 0 : opts.selectedItemID) && clsIDs.includes(opts.selectedItemID);
29
+ const isSelected = (opts === null || opts === void 0 ? void 0 : opts.selectedItemID) && groupLabel === opts.selectedItemID ? true : false;
30
+ const isExpanded = hasSelectedClass || ((_a = opts === null || opts === void 0 ? void 0 : opts.expandedGroupLabels) === null || _a === void 0 ? void 0 : _a.has(groupLabel));
31
+ return {
32
+ id: groupLabel,
33
+ label: groupLabel,
34
+ hasCaret: true,
35
+ isSelected,
36
+ isExpanded,
37
+ icon: isExpanded ? 'folder-open' : 'folder-close',
38
+ childNodes: isExpanded ? getItemClassesAsTreeNodes(itemClasses, clsIDs, opts) : [],
39
+ nodeData: {
40
+ type: 'group'
41
+ }
42
+ };
43
+ });
44
+ }
45
+ }
46
+
47
+ function getItemClassesAsTreeNodes(itemClasses,
48
+ /** Used for ordering. */
49
+ classIDs, opts) {
50
+ return classIDs.map(clsID => {
51
+ var _a;
52
+
53
+ const cls = itemClasses[clsID];
54
+ return {
55
+ id: clsID,
56
+ label: (_a = cls === null || cls === void 0 ? void 0 : cls.meta.title) !== null && _a !== void 0 ? _a : 'unknown class',
57
+ icon: 'folder-close',
58
+ isSelected: (opts === null || opts === void 0 ? void 0 : opts.selectedItemID) === clsID,
59
+ nodeData: {
60
+ type: 'item'
61
+ },
62
+ secondaryLabel: (0, _react.jsx)(_util.MoreMenu, null, (0, _react.jsx)(_util.ItemClassMenu, {
63
+ cfg: cls,
64
+ onCreate: (opts === null || opts === void 0 ? void 0 : opts.onProposeItem) ? () => opts.onProposeItem(clsID) : undefined
65
+ }))
66
+ };
67
+ });
68
+ }
@@ -0,0 +1 @@
1
+ {"version":3,"file":"treeNodes.js","sourceRoot":"","sources":["../../src/item-classes/treeNodes.tsx"],"names":[],"mappings":"AAAA,eAAe;AACf,8BAA8B;AAE9B;;;GAGG;AAEH,qDAAqD;AACrD,OAAO,EAAE,GAAG,EAAE,MAAM,gBAAgB,CAAC;AAGrC,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAMxD,MAAM,UAAU,qCAAqC,CACnD,WAAwC,EACxC,eAAiD,EACjD,IAIC;IAED,IAAI,CAAC,eAAe,EAAE;QACpB,OAAO,yBAAyB,CAAC,WAAW,EAAE,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,IAAI,CAAC,CAAC;KAC/E;SAAM;QACL,OAAO,MAAM,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,UAAU,EAAE,MAAM,CAAC,EAAE,EAAE;;YAClE,MAAM,gBAAgB,GAAG,CAAA,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,cAAc,KAAI,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;YACtF,MAAM,UAAU,GAAG,CAAA,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,cAAc,KAAI,UAAU,KAAK,IAAI,CAAC,cAAc;gBAC3E,CAAC,CAAC,IAAI;gBACN,CAAC,CAAC,KAAK,CAAC;YACV,MAAM,UAAU,GAAG,gBAAgB,KAAI,MAAA,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,mBAAmB,0CAAE,GAAG,CAAC,UAAU,CAAC,CAAA,CAAC;YAClF,OAAO;gBACL,EAAE,EAAE,UAAU;gBACd,KAAK,EAAE,UAAU;gBACjB,QAAQ,EAAE,IAAI;gBACd,UAAU;gBACV,UAAU;gBACV,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,cAA0B;gBAC7D,UAAU,EAAE,UAAU;oBACpB,CAAC,CAAC,yBAAyB,CAAC,WAAW,EAAE,MAAM,EAAE,IAAI,CAAC;oBACtD,CAAC,CAAC,EAAE;gBACN,QAAQ,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE;aAC5B,CAAC;QACJ,CAAC,CAAC,CAAC;KACJ;AACH,CAAC;AAED,SAAS,yBAAyB,CAChC,WAAc;AACd,yBAAyB;AACzB,QAA8B,EAC9B,IAGC;IAED,OAAO,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE;;QAC1B,MAAM,GAAG,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC;QAC/B,OAAO;YACL,EAAE,EAAE,KAAe;YACnB,KAAK,EAAE,MAAA,GAAG,aAAH,GAAG,uBAAH,GAAG,CAAE,IAAI,CAAC,KAAK,mCAAI,eAAe;YACzC,IAAI,EAAE,cAAc;YACpB,UAAU,EAAE,CAAA,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,cAAc,MAAK,KAAK;YAC1C,QAAQ,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE;YAC1B,cAAc,EACZ,IAAC,QAAQ;gBACP,IAAC,aAAa,IACZ,GAAG,EAAE,GAAG,EACR,QAAQ,EAAE,CAAA,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,aAAa,EAAC,CAAC;wBAC7B,GAAG,EAAE,CAAC,IAAI,CAAC,aAAc,CAAC,KAAe,CAAC;wBAC1C,CAAC,CAAC,SAAS,GACb,CACO;SACd,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC","sourcesContent":["/** @jsx jsx */\n/** @jsxFrag React.Fragment */\n\n/**\n * Tools for rendering proposal groups as tree nodes.\n * Each proposal group is top-level node, with proposals as nested nodes.\n */\n\n//import React, { useContext, useMemo } from 'react';\nimport { jsx } from '@emotion/react';\nimport type { RegistryViewProps } from '../types/views';\nimport type { TreeNodeInfo, IconName } from '@blueprintjs/core';\nimport { MoreMenu, ItemClassMenu } from '../views/util';\n\n\nexport type ItemOrGroupTreeNode = TreeNodeInfo<{ type: 'group' | 'item' }>;\n\n\nexport function getMaybeGroupedItemClassesAsTreeNodes<T extends RegistryViewProps>(\n itemClasses: T['itemClassConfiguration'],\n itemClassGroups: T['itemClassGroups'] | undefined,\n opts?: {\n expandedGroupLabels?: Set<string>\n selectedItemID?: string\n onProposeItem?: (clsID: string) => Promise<void>\n },\n): ItemOrGroupTreeNode[] {\n if (!itemClassGroups) {\n return getItemClassesAsTreeNodes(itemClasses, Object.keys(itemClasses), opts);\n } else {\n return Object.entries(itemClassGroups).map(([groupLabel, clsIDs]) => {\n const hasSelectedClass = opts?.selectedItemID && clsIDs.includes(opts.selectedItemID);\n const isSelected = opts?.selectedItemID && groupLabel === opts.selectedItemID\n ? true\n : false;\n const isExpanded = hasSelectedClass || opts?.expandedGroupLabels?.has(groupLabel);\n return {\n id: groupLabel,\n label: groupLabel,\n hasCaret: true,\n isSelected,\n isExpanded,\n icon: isExpanded ? 'folder-open' : 'folder-close' as IconName,\n childNodes: isExpanded\n ? getItemClassesAsTreeNodes(itemClasses, clsIDs, opts)\n : [],\n nodeData: { type: 'group' },\n };\n });\n }\n}\n\nfunction getItemClassesAsTreeNodes<T extends RegistryViewProps['itemClassConfiguration']>(\n itemClasses: T,\n /** Used for ordering. */\n classIDs: readonly (keyof T)[],\n opts?: {\n selectedItemID?: string\n onProposeItem?: (clsID: string) => Promise<void>\n },\n): TreeNodeInfo<{ type: 'item' }>[] {\n return classIDs.map(clsID => {\n const cls = itemClasses[clsID];\n return {\n id: clsID as string,\n label: cls?.meta.title ?? 'unknown class',\n icon: 'folder-close',\n isSelected: opts?.selectedItemID === clsID,\n nodeData: { type: 'item' },\n secondaryLabel:\n <MoreMenu>\n <ItemClassMenu\n cfg={cls}\n onCreate={opts?.onProposeItem ?\n () => opts.onProposeItem!(clsID as string)\n : undefined}\n />\n </MoreMenu>,\n };\n });\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@riboseinc/paneron-registry-kit",
3
- "version": "2.2.30",
3
+ "version": "2.2.32",
4
4
  "main": "index.js",
5
5
  "author": "Ribose Inc. <open.source@ribose.com>",
6
6
  "scripts": {
@@ -28,7 +28,7 @@
28
28
  "@blueprintjs/select": "~4.9.10",
29
29
  "@emotion/react": "^11.10.6",
30
30
  "@emotion/styled": "^11.10.6",
31
- "@riboseinc/paneron-extension-kit": "2.2.16",
31
+ "@riboseinc/paneron-extension-kit": "2.2.20",
32
32
  "@types/react": "17.0.53",
33
33
  "@types/react-dom": "^17.0.2",
34
34
  "@types/react-helmet": "^6.1.2",
@@ -0,0 +1,7 @@
1
+ /** @jsx jsx */
2
+ /** @jsxFrag React.Fragment */
3
+ import React from 'react';
4
+ declare const ActionableCRTree: React.FC<{
5
+ className?: string;
6
+ }>;
7
+ export default ActionableCRTree;
@@ -0,0 +1,179 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+
8
+ var _react = require("react");
9
+
10
+ var _immutabilityHelper = _interopRequireDefault(require("immutability-helper"));
11
+
12
+ var _react2 = require("@emotion/react");
13
+
14
+ var _core = require("@blueprintjs/core");
15
+
16
+ var _paneronExtensionKit = require("@riboseinc/paneron-extension-kit");
17
+
18
+ var _ChangeRequestContext = require("../../views/change-request/ChangeRequestContext");
19
+
20
+ var _BrowserCtx = require("../../views/BrowserCtx");
21
+
22
+ var _queries = require("./queries");
23
+
24
+ var _treeNodes = require("./treeNodes");
25
+
26
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
27
+
28
+ /** @jsx jsx */
29
+
30
+ /** @jsxFrag React.Fragment */
31
+ const initialState = {
32
+ //selectedFolderID: null,
33
+ selectedItemID: null,
34
+ expandedFolderIDs: []
35
+ };
36
+
37
+ const ActionableCRTree = function ({
38
+ className
39
+ }) {
40
+ var _a;
41
+
42
+ const {
43
+ changeRequest: activeCR
44
+ } = (0, _react.useContext)(_ChangeRequestContext.ChangeRequestContext);
45
+ const {
46
+ setActiveChangeRequestID,
47
+ stakeholder
48
+ } = (0, _react.useContext)(_BrowserCtx.BrowserCtx);
49
+ const {
50
+ usePersistentDatasetStateReducer,
51
+ useMapReducedData
52
+ } = (0, _react.useContext)(_paneronExtensionKit.DatasetContext);
53
+ const [state, dispatch] = usePersistentDatasetStateReducer('actionable-proposals', undefined, undefined, (prevState, action) => {
54
+ switch (action.type) {
55
+ case 'select-folder':
56
+ if (prevState.selectedItemID !== action.payload.folderID) {
57
+ return { ...prevState,
58
+ selectedItemID: action.payload.folderID
59
+ };
60
+ } else {
61
+ return prevState;
62
+ }
63
+
64
+ case 'enter-folder':
65
+ if (!prevState.expandedFolderIDs.includes(action.payload.folderID)) {
66
+ return { ...prevState,
67
+ selectedItemID: action.payload.folderID,
68
+ expandedFolderIDs: (0, _immutabilityHelper.default)(prevState.expandedFolderIDs, {
69
+ $push: [action.payload.folderID]
70
+ })
71
+ };
72
+ } else {
73
+ return prevState;
74
+ }
75
+
76
+ case 'exit-folder':
77
+ const idx = prevState.expandedFolderIDs.indexOf(action.payload.folderID);
78
+
79
+ if (idx >= 0) {
80
+ return { ...prevState,
81
+ selectedItemID: action.payload.folderID,
82
+ expandedFolderIDs: (0, _immutabilityHelper.default)(prevState.expandedFolderIDs, {
83
+ $splice: [[idx, 1]]
84
+ })
85
+ };
86
+ } else {
87
+ return prevState;
88
+ }
89
+
90
+ case 'select-item':
91
+ if (prevState.selectedItemID !== action.payload.itemID) {
92
+ return { ...prevState,
93
+ selectedItemID: action.payload.itemID
94
+ };
95
+ } else {
96
+ return prevState;
97
+ }
98
+
99
+ default:
100
+ throw new Error("Unexpected browse state");
101
+ }
102
+ }, initialState, null);
103
+ const groups = (0, _queries.getActionableProposalGroupsForRoles)((_a = stakeholder === null || stakeholder === void 0 ? void 0 : stakeholder.roles) !== null && _a !== void 0 ? _a : []);
104
+ const chains = stakeholder ? (0, _treeNodes.getMapReduceChainsForActionableProposalGroups)(groups, stakeholder) : {};
105
+ const actionableProposalsResult = useMapReducedData({
106
+ chains
107
+ });
108
+ const actionableProposals = (0, _react.useMemo)(() => Object.entries(actionableProposalsResult.value).map(([chainID, chainResult]) => ({
109
+ groupLabel: chainID,
110
+ proposals: (Array.isArray(chainResult) // TODO: Validate results
111
+ ? chainResult : undefined) || undefined
112
+ })), [actionableProposalsResult.value]);
113
+ const nodes = (0, _react.useMemo)(() => (0, _treeNodes.getActionableProposalGroupsAsTreeNodes)(actionableProposals, {
114
+ activeCRID: activeCR === null || activeCR === void 0 ? void 0 : activeCR.id,
115
+ expandedGroupLabels: new Set(state.expandedFolderIDs),
116
+ selectedGroup: state.selectedItemID ? actionableProposals.find(({
117
+ groupLabel
118
+ }) => groupLabel === state.selectedItemID) ? state.selectedItemID : undefined : undefined,
119
+ selectedCRID: state.selectedItemID ? actionableProposals.flatMap(({
120
+ proposals
121
+ }) => proposals !== null && proposals !== void 0 ? proposals : []).find(p => p.id === state.selectedItemID) ? state.selectedItemID : undefined : undefined
122
+ }), [activeCR === null || activeCR === void 0 ? void 0 : activeCR.id, actionableProposals, state.selectedItemID, state.expandedFolderIDs.join(',')]);
123
+ const eventHandlers = (0, _react.useMemo)(() => ({
124
+ onNodeClick: node => {
125
+ var _a;
126
+
127
+ return ((_a = node.nodeData) === null || _a === void 0 ? void 0 : _a.type) === 'group' ? dispatch({
128
+ type: 'select-folder',
129
+ payload: {
130
+ folderID: node.id
131
+ }
132
+ }) : dispatch({
133
+ type: 'select-item',
134
+ payload: {
135
+ itemID: node.id
136
+ }
137
+ });
138
+ },
139
+ onNodeExpand: node => {
140
+ var _a;
141
+
142
+ return ((_a = node.nodeData) === null || _a === void 0 ? void 0 : _a.type) === 'group' ? dispatch({
143
+ type: 'enter-folder',
144
+ payload: {
145
+ folderID: node.id
146
+ }
147
+ }) : void 0;
148
+ },
149
+ onNodeCollapse: node => {
150
+ var _a;
151
+
152
+ return ((_a = node.nodeData) === null || _a === void 0 ? void 0 : _a.type) === 'group' ? dispatch({
153
+ type: 'exit-folder',
154
+ payload: {
155
+ folderID: node.id
156
+ }
157
+ }) : void 0;
158
+ },
159
+ onNodeDoubleClick: node => {
160
+ var _a;
161
+
162
+ return ((_a = node.nodeData) === null || _a === void 0 ? void 0 : _a.type) === 'group' ? dispatch({
163
+ type: 'enter-folder',
164
+ payload: {
165
+ folderID: node.id
166
+ }
167
+ }) // TODO: Do something like switch to home tab or proposal tab?
168
+ : node.id === (activeCR === null || activeCR === void 0 ? void 0 : activeCR.id) ? setActiveChangeRequestID === null || setActiveChangeRequestID === void 0 ? void 0 : setActiveChangeRequestID(null) : setActiveChangeRequestID === null || setActiveChangeRequestID === void 0 ? void 0 : setActiveChangeRequestID(node.id);
169
+ }
170
+ }), [dispatch, activeCR === null || activeCR === void 0 ? void 0 : activeCR.id]);
171
+ return (0, _react2.jsx)(_core.Tree, {
172
+ className: className,
173
+ contents: nodes,
174
+ ...eventHandlers
175
+ });
176
+ };
177
+
178
+ var _default = ActionableCRTree;
179
+ exports.default = _default;
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Tree.js","sourceRoot":"","sources":["../../../src/proposals/actionableGroups/Tree.tsx"],"names":[],"mappings":"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","sourcesContent":["/** @jsx jsx */\n/** @jsxFrag React.Fragment */\n\nimport React, { useContext, useMemo } from 'react';\nimport update from 'immutability-helper';\nimport { jsx } from '@emotion/react';\nimport { Tree } from '@blueprintjs/core';\nimport { DatasetContext } from '@riboseinc/paneron-extension-kit';\nimport type { PersistentStateReducerHook } from '@riboseinc/paneron-extension-kit/usePersistentStateReducer';\nimport type { SomeCR as CR } from '../../types/cr';\nimport { ChangeRequestContext } from '../../views/change-request/ChangeRequestContext';\nimport { BrowserCtx } from '../../views/BrowserCtx';\nimport { getActionableProposalGroupsForRoles } from './queries';\nimport {\n type ActionableProposalTreeNode,\n getMapReduceChainsForActionableProposalGroups,\n getActionableProposalGroupsAsTreeNodes,\n} from './treeNodes';\n\n\ninterface State {\n //selectedFolderID: string | null\n selectedItemID: string | null\n expandedFolderIDs: readonly string[]\n}\n\nconst initialState: State = {\n //selectedFolderID: null,\n selectedItemID: null,\n expandedFolderIDs: [],\n} as const;\n\ntype Action =\n | { type: 'select-folder'; payload: { folderID: string | null; }; }\n | { type: 'enter-folder'; payload: { folderID: string; }; }\n | { type: 'exit-folder'; payload: { folderID: string; }; }\n | { type: 'select-item'; payload: { itemID: string | null; }; }\n\n\nconst ActionableCRTree: React.FC<{\n className?: string\n}> =\nfunction ({ className }) {\n const { changeRequest: activeCR } = useContext(ChangeRequestContext);\n const { setActiveChangeRequestID, stakeholder } = useContext(BrowserCtx);\n const { usePersistentDatasetStateReducer, useMapReducedData } = useContext(DatasetContext);\n\n const [ state, dispatch, ] = (usePersistentDatasetStateReducer as PersistentStateReducerHook<State, Action>)(\n 'actionable-proposals',\n undefined,\n undefined,\n (prevState, action) => {\n switch (action.type) {\n case 'select-folder':\n if (prevState.selectedItemID !== action.payload.folderID) {\n return {\n ...prevState,\n selectedItemID: action.payload.folderID,\n };\n } else {\n return prevState;\n }\n case 'enter-folder':\n if (!prevState.expandedFolderIDs.includes(action.payload.folderID)) {\n return {\n ...prevState,\n selectedItemID: action.payload.folderID,\n expandedFolderIDs: update(\n prevState.expandedFolderIDs,\n { $push: [action.payload.folderID] }),\n };\n } else {\n return prevState;\n }\n case 'exit-folder':\n const idx = prevState.expandedFolderIDs.indexOf(action.payload.folderID);\n if (idx >= 0) {\n return {\n ...prevState,\n selectedItemID: action.payload.folderID,\n expandedFolderIDs: update(\n prevState.expandedFolderIDs,\n { $splice: [[idx, 1]] }),\n };\n } else {\n return prevState;\n }\n case 'select-item':\n if (prevState.selectedItemID !== action.payload.itemID) {\n return {\n ...prevState,\n selectedItemID: action.payload.itemID,\n };\n } else {\n return prevState;\n }\n default:\n throw new Error(\"Unexpected browse state\");\n }\n },\n initialState,\n null);\n\n const groups = getActionableProposalGroupsForRoles(stakeholder?.roles ?? []);\n\n const chains = stakeholder\n ? getMapReduceChainsForActionableProposalGroups(groups, stakeholder)\n : {};\n\n const actionableProposalsResult = useMapReducedData({ chains });\n\n const actionableProposals = useMemo(\n (() =>\n Object.entries(actionableProposalsResult.value).\n map(([chainID, chainResult]) => ({\n groupLabel: chainID,\n proposals: (Array.isArray(chainResult)\n // TODO: Validate results\n ? (chainResult as CR[])\n : undefined) || undefined\n }))\n ),\n [actionableProposalsResult.value]);\n\n const nodes = useMemo(\n (() =>\n getActionableProposalGroupsAsTreeNodes(actionableProposals, {\n activeCRID: activeCR?.id,\n expandedGroupLabels: new Set(state.expandedFolderIDs),\n selectedGroup: state.selectedItemID\n ? actionableProposals.\n find(({ groupLabel }) => groupLabel === state.selectedItemID)\n ? state.selectedItemID\n : undefined\n : undefined,\n selectedCRID: state.selectedItemID\n ? actionableProposals.\n flatMap(({ proposals }) => proposals ?? []).\n find(p => p.id === state.selectedItemID)\n ? state.selectedItemID\n : undefined\n : undefined,\n })\n ),\n [activeCR?.id, actionableProposals, state.selectedItemID, state.expandedFolderIDs.join(',')]);\n\n const eventHandlers = useMemo((() => ({\n onNodeClick: (node: ActionableProposalTreeNode) =>\n node.nodeData?.type === 'group'\n ? dispatch({\n type: 'select-folder',\n payload: { folderID: node.id as string },\n })\n : dispatch({\n type: 'select-item',\n payload: { itemID: node.id as string },\n }),\n onNodeExpand: (node: ActionableProposalTreeNode) =>\n node.nodeData?.type === 'group'\n ? dispatch({\n type: 'enter-folder',\n payload: { folderID: node.id as string },\n })\n : void 0,\n onNodeCollapse: (node: ActionableProposalTreeNode) =>\n node.nodeData?.type === 'group'\n ? dispatch({\n type: 'exit-folder',\n payload: { folderID: node.id as string },\n })\n : void 0,\n onNodeDoubleClick: (node: ActionableProposalTreeNode) =>\n node.nodeData?.type === 'group'\n ? dispatch({\n type: 'enter-folder',\n payload: { folderID: node.id as string },\n })\n // TODO: Do something like switch to home tab or proposal tab?\n : node.id === activeCR?.id\n ? setActiveChangeRequestID?.(null)\n : setActiveChangeRequestID?.(node.id as string),\n })), [dispatch, activeCR?.id]);\n\n return <Tree\n className={className}\n contents={nodes}\n {...eventHandlers}\n />;\n}\n\nexport default ActionableCRTree;\n"]}
@@ -0,0 +1,5 @@
1
+ import type { StakeholderRoleType } from '../../types';
2
+ import type { ActionableProposalGroup } from './types';
3
+ export declare function getActionableProposalGroupsForRole(role: StakeholderRoleType): readonly ActionableProposalGroup[];
4
+ export declare function getActionableProposalGroupsForRoles(roles: readonly StakeholderRoleType[]): readonly ActionableProposalGroup[];
5
+ export declare const CR_BASE_QUERY = "objPath.indexOf(\"/proposals/\") === 0 && objPath.endsWith(\"main.yaml\")";
@@ -0,0 +1,81 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.getActionableProposalGroupsForRole = getActionableProposalGroupsForRole;
7
+ exports.getActionableProposalGroupsForRoles = getActionableProposalGroupsForRoles;
8
+ exports.CR_BASE_QUERY = void 0;
9
+
10
+ var _cr = require("../../types/cr");
11
+
12
+ function getActionableProposalGroupsForRole(role) {
13
+ return CR_QUERIES_FOR_ROLES.filter(([, roles]) => roles.has(role));
14
+ }
15
+
16
+ function getActionableProposalGroupsForRoles(roles) {
17
+ return roles.flatMap(getActionableProposalGroupsForRole);
18
+ }
19
+
20
+ const CR_BASE_QUERY = 'objPath.indexOf("/proposals/") === 0 && objPath.endsWith("main.yaml")';
21
+ exports.CR_BASE_QUERY = CR_BASE_QUERY;
22
+ const CR_QUERIES_FOR_ROLES = [['My Drafts', new Set(['submitter', 'manager', 'control-body', 'owner']), function submitterProposals(stakeholder) {
23
+ if (stakeholder && stakeholder.gitServerUsername) {
24
+ const stakeholderCondition = `obj.submittingStakeholderGitServerUsername === "${stakeholder.gitServerUsername}"`;
25
+ const query = `(obj.state === "${_cr.State.DRAFT}" || obj.state === "${_cr.State.RETURNED_FOR_CLARIFICATION}") && (${stakeholderCondition})`;
26
+ return query;
27
+ } else {
28
+ return 'false';
29
+ }
30
+ }], ['My Rejected', new Set(['submitter', 'manager', 'control-body', 'owner']), function submitterProposals(stakeholder) {
31
+ // Rejections are actionable because they can be appealed by the submitter.
32
+ if (stakeholder && stakeholder.gitServerUsername) {
33
+ const stakeholderCondition = `obj.submittingStakeholderGitServerUsername === "${stakeholder.gitServerUsername}"`;
34
+ const query = `(obj.state === "${_cr.State.REJECTED}") && (${stakeholderCondition})`;
35
+ return query;
36
+ } else {
37
+ return 'false';
38
+ }
39
+ }], ['Everyone’s Drafts or Returned', new Set(['manager', 'control-body', 'owner']), function submitterProposals(stakeholder) {
40
+ if (stakeholder && stakeholder.gitServerUsername) {
41
+ const stakeholderCondition = `obj.submittingStakeholderGitServerUsername !== "${stakeholder.gitServerUsername}"`;
42
+ const query = `(obj.state === "${_cr.State.DRAFT}" || obj.state === "${_cr.State.RETURNED_FOR_CLARIFICATION}") && (${stakeholderCondition})`;
43
+ return query;
44
+ } else {
45
+ return 'false';
46
+ }
47
+ }], // ['latest reviewed', new Set(['submitter', 'manager', 'control-body', 'owner']), function submitterProposals(stakeholder) {
48
+ // // TODO: Should filter only rejected perhaps?
49
+ // // Approved/accepted proposals can be shown in another (public) area.
50
+ // if (stakeholder && stakeholder.gitServerUsername) {
51
+ // const stakeholderCondition = stakeholder?.role !== 'submitter'
52
+ // ? 'true'
53
+ // : `obj.submittingStakeholderGitServerUsername === "${stakeholder.gitServerUsername}"`;
54
+ // // Don’t show drafts in the list of pending proposals, unless it’s user’s own drafts.
55
+ // const query = `(obj.state === "${State.ACCEPTED} || obj.state === "${State.REJECTED} || obj.state === "${State.REJECTION_UPHELD_ON_APPEAL}"") && ${stakeholderCondition}`;
56
+ // return query;
57
+ // } else {
58
+ // return 'false';
59
+ // }
60
+ // // TODO: Implement limit
61
+ // }],
62
+ // ['latest withdrawn', new Set(['submitter', 'manager', 'control-body', 'owner']), function submitterProposals(stakeholder) {
63
+ // if (stakeholder && stakeholder.gitServerUsername) {
64
+ // const stakeholderCondition = stakeholder?.role !== 'submitter'
65
+ // ? 'true'
66
+ // : `obj.submittingStakeholderGitServerUsername === "${stakeholder.gitServerUsername}"`;
67
+ // // Don’t show drafts in the list of pending proposals, unless it’s user’s own drafts.
68
+ // const query = `(obj.state === "${State.WITHDRAWN}" || obj.state === "${State.APPEAL_WITHDRAWN}") && ${stakeholderCondition}`;
69
+ // return query;
70
+ // } else {
71
+ // return 'false';
72
+ // }
73
+ // // TODO: Implement limit
74
+ // }],
75
+ ['Pending Owner Appeal Review', new Set(['owner']), function ownerProposals() {
76
+ return `obj.state === "${_cr.State.APPEALED}"`;
77
+ }], ['Pending Control Body Review', new Set(['control-body', 'owner']), function cbProposals() {
78
+ return `obj.state === "${_cr.State.SUBMITTED_FOR_CONTROL_BODY_REVIEW}"`;
79
+ }], ['Pending Manager Review', new Set(['manager', 'control-body', 'owner']), function managerProposals() {
80
+ return `obj.state === "${_cr.State.PROPOSED}"`;
81
+ }]];
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queries.js","sourceRoot":"","sources":["../../../src/proposals/actionableGroups/queries.ts"],"names":[],"mappings":"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","sourcesContent":["import { State } from '../../types/cr';\nimport type { StakeholderRoleType } from '../../types';\nimport type { ActionableProposalGroup } from './types';\n\n\nexport function getActionableProposalGroupsForRole(role: StakeholderRoleType): readonly ActionableProposalGroup[] {\n return CR_QUERIES_FOR_ROLES.filter(([, roles]) => roles.has(role));\n}\n\nexport function getActionableProposalGroupsForRoles(roles: readonly StakeholderRoleType[]): readonly ActionableProposalGroup[] {\n return roles.flatMap(getActionableProposalGroupsForRole);\n}\n\n\nexport const CR_BASE_QUERY = 'objPath.indexOf(\"/proposals/\") === 0 && objPath.endsWith(\"main.yaml\")';\n\nconst CR_QUERIES_FOR_ROLES: readonly ActionableProposalGroup[] =\n[\n ['My Drafts', new Set(['submitter', 'manager', 'control-body', 'owner']), function submitterProposals(stakeholder) {\n if (stakeholder && stakeholder.gitServerUsername) {\n const stakeholderCondition = `obj.submittingStakeholderGitServerUsername === \"${stakeholder.gitServerUsername}\"`;\n const query = `(obj.state === \"${State.DRAFT}\" || obj.state === \"${State.RETURNED_FOR_CLARIFICATION}\") && (${stakeholderCondition})`;\n return query;\n } else {\n return 'false';\n }\n }],\n ['My Rejected', new Set(['submitter', 'manager', 'control-body', 'owner']), function submitterProposals(stakeholder) {\n // Rejections are actionable because they can be appealed by the submitter.\n if (stakeholder && stakeholder.gitServerUsername) {\n const stakeholderCondition = `obj.submittingStakeholderGitServerUsername === \"${stakeholder.gitServerUsername}\"`;\n const query = `(obj.state === \"${State.REJECTED}\") && (${stakeholderCondition})`;\n return query;\n } else {\n return 'false';\n }\n }],\n ['Everyone’s Drafts or Returned', new Set(['manager', 'control-body', 'owner']), function submitterProposals(stakeholder) {\n if (stakeholder && stakeholder.gitServerUsername) {\n const stakeholderCondition = `obj.submittingStakeholderGitServerUsername !== \"${stakeholder.gitServerUsername}\"`;\n const query = `(obj.state === \"${State.DRAFT}\" || obj.state === \"${State.RETURNED_FOR_CLARIFICATION}\") && (${stakeholderCondition})`;\n return query;\n } else {\n return 'false';\n }\n }],\n // ['latest reviewed', new Set(['submitter', 'manager', 'control-body', 'owner']), function submitterProposals(stakeholder) {\n // // TODO: Should filter only rejected perhaps?\n // // Approved/accepted proposals can be shown in another (public) area.\n // if (stakeholder && stakeholder.gitServerUsername) {\n // const stakeholderCondition = stakeholder?.role !== 'submitter'\n // ? 'true'\n // : `obj.submittingStakeholderGitServerUsername === \"${stakeholder.gitServerUsername}\"`;\n // // Don’t show drafts in the list of pending proposals, unless it’s user’s own drafts.\n // const query = `(obj.state === \"${State.ACCEPTED} || obj.state === \"${State.REJECTED} || obj.state === \"${State.REJECTION_UPHELD_ON_APPEAL}\"\") && ${stakeholderCondition}`;\n // return query;\n // } else {\n // return 'false';\n // }\n // // TODO: Implement limit\n // }],\n // ['latest withdrawn', new Set(['submitter', 'manager', 'control-body', 'owner']), function submitterProposals(stakeholder) {\n // if (stakeholder && stakeholder.gitServerUsername) {\n // const stakeholderCondition = stakeholder?.role !== 'submitter'\n // ? 'true'\n // : `obj.submittingStakeholderGitServerUsername === \"${stakeholder.gitServerUsername}\"`;\n // // Don’t show drafts in the list of pending proposals, unless it’s user’s own drafts.\n // const query = `(obj.state === \"${State.WITHDRAWN}\" || obj.state === \"${State.APPEAL_WITHDRAWN}\") && ${stakeholderCondition}`;\n // return query;\n // } else {\n // return 'false';\n // }\n // // TODO: Implement limit\n // }],\n ['Pending Owner Appeal Review', new Set(['owner']), function ownerProposals() {\n return `obj.state === \"${State.APPEALED}\"`;\n }],\n ['Pending Control Body Review', new Set(['control-body', 'owner']), function cbProposals() {\n return `obj.state === \"${State.SUBMITTED_FOR_CONTROL_BODY_REVIEW}\"`;\n }],\n ['Pending Manager Review', new Set(['manager', 'control-body', 'owner']), function managerProposals() {\n return `obj.state === \"${State.PROPOSED}\"`;\n }],\n] as const;\n"]}
@@ -0,0 +1,26 @@
1
+ /** @jsx jsx */
2
+ /** @jsxFrag React.Fragment */
3
+ import type { TreeNodeInfo } from '@blueprintjs/core';
4
+ import type { RegisterStakeholder } from '../../types';
5
+ import type { SomeCR as CR } from '../../types/cr';
6
+ import type { ActionableProposalGroup } from './types';
7
+ export declare type ActionableProposalTreeNode = TreeNodeInfo<{
8
+ type: 'group' | 'item';
9
+ }>;
10
+ interface ActionableProposalGroupResult {
11
+ groupLabel: string;
12
+ proposals: CR[] | undefined;
13
+ }
14
+ export declare function getActionableProposalGroupsAsTreeNodes(groups: readonly ActionableProposalGroupResult[], opts?: {
15
+ expandedGroupLabels?: Set<string>;
16
+ selectedGroup?: string;
17
+ selectedCRID?: string;
18
+ activeCRID?: string;
19
+ }): ActionableProposalTreeNode[];
20
+ export declare function getMapReduceChainsForActionableProposalGroups(proposalGroups: readonly ActionableProposalGroup[], stakeholder: RegisterStakeholder): {
21
+ [x: string]: {
22
+ mapFunc: string;
23
+ predicateFunc: string;
24
+ };
25
+ };
26
+ export {};