@riboseinc/paneron-registry-kit 2.2.35 → 2.2.37
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/package.json +2 -2
- package/proposals/ListItem.d.ts +1 -0
- package/proposals/ListItem.js +4 -1
- package/proposals/ListItem.js.map +1 -1
- package/proposals/MetaProperties.d.ts +4 -3
- package/proposals/MetaProperties.js +26 -19
- package/proposals/MetaProperties.js.map +1 -1
- package/proposals/ProposalBrowser.d.ts +8 -1
- package/proposals/ProposalBrowser.js +2 -1
- package/proposals/ProposalBrowser.js.map +1 -1
- package/proposals/ProposalTab.d.ts +2 -0
- package/proposals/ProposalTab.js +13 -1
- package/proposals/ProposalTab.js.map +1 -1
- package/proposals/ProposalWorkspace.d.ts +3 -1
- package/proposals/ProposalWorkspace.js +9 -7
- package/proposals/ProposalWorkspace.js.map +1 -1
- package/proposals/TransitionHistory.js +10 -4
- package/proposals/TransitionHistory.js.map +1 -1
- package/proposals/actionableGroups/Tree.js +15 -0
- package/proposals/actionableGroups/Tree.js.map +1 -1
- package/proposals/actionableGroups/treeNodes.js +9 -5
- package/proposals/actionableGroups/treeNodes.js.map +1 -1
- package/proposals/types.d.ts +1 -0
- package/proposals/types.js +5 -0
- package/proposals/types.js.map +1 -1
- package/views/detail/AllItems.d.ts +8 -0
- package/views/detail/AllItems.js +45 -0
- package/views/detail/AllItems.js.map +1 -0
- package/views/detail/ProposalWork.js +3 -1
- package/views/detail/ProposalWork.js.map +1 -1
- package/views/detail/RegisterHome/ActiveProposalDetails.js +6 -1
- package/views/detail/RegisterHome/ActiveProposalDetails.js.map +1 -1
- package/views/detail/RegisterHome2/index.js +11 -2
- package/views/detail/RegisterHome2/index.js.map +1 -1
- package/views/sidebar/Search/index.d.ts +2 -0
- package/views/sidebar/Search/index.js +14 -2
- package/views/sidebar/Search/index.js.map +1 -1
- package/views/sidebar/index.js +9 -3
- package/views/sidebar/index.js.map +1 -1
- package/views/util.d.ts +8 -0
- package/views/util.js +10 -3
- package/views/util.js.map +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TransitionHistory.js","sourceRoot":"","sources":["../../src/proposals/TransitionHistory.tsx"],"names":[],"mappings":"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","sourcesContent":["/** @jsx jsx */\n/** @jsxFrag React.Fragment */\n\nimport styled from '@emotion/styled';\nimport { jsx, css } from '@emotion/react';\nimport React from 'react';\nimport { Icon, Colors } from '@blueprintjs/core';\n\nimport { normalizeObjectRecursively } from '@riboseinc/paneron-extension-kit/util';\nimport HelpTooltip from '@riboseinc/paneron-extension-kit/widgets/HelpTooltip';\n\nimport { Val } from '../views/diffing/InlineDiff';\nimport { registerStakeholderPlain } from '../views/RegisterStakeholder';\nimport { type RegisterStakeholder } from '../types/stakeholder';\n\nimport * as CR from './types';\nimport { STATE_COLOR } from './TransitionOptions';\n\n\n/**\n * Transition history entry is mostly like `CR.TransitionEntry`,\n * except it has optional fields and can be `undefined` to represent\n * missing parts of history.\n */\nexport type TransitionHistoryEntry = Omit<CR.TransitionEntry, 'timestamp' | 'fromState' | 'stakeholder' | 'input'> & {\n timestamp?: Date\n fromState?: CR.StateType\n stakeholder?: RegisterStakeholder\n input?: CR.StateInput\n} | undefined;\n\n\n/**\n * Outputs transition history,\n * back-filling it from state and timestamps if `pastTransitions` is not present.\n */\nexport function getTransitionHistory(cr: CR.Base): TransitionHistoryEntry[] {\n if (cr.pastTransitions && cr.pastTransitions.length > 0) {\n return [{\n label: \"Create\",\n toState: CR.State.DRAFT,\n timestamp: (cr as CR.Drafted).timeStarted,\n }, ...cr.pastTransitions];\n\n } else {\n const els: TransitionHistoryEntry[] = [];\n\n els.push({\n label: \"Create\",\n toState: CR.State.DRAFT,\n timestamp: (cr as CR.Drafted).timeStarted,\n });\n\n if (!CR.isDrafted(cr)) {\n els.push(undefined);\n }\n\n // Backward compatibility\n\n if (CR.isProposed(cr)) {\n els.push({\n label: \"Propose\",\n toState: CR.State.PROPOSED,\n timestamp: cr.timeProposed,\n input: { justification: cr.justification },\n });\n }\n\n if (CR.isSubmittedForControlBodyReview(cr)) {\n els.push({\n label: \"Submit for control body review\",\n fromState: CR.State.PROPOSED,\n toState: CR.State.SUBMITTED_FOR_CONTROL_BODY_REVIEW,\n input: { registerManagerNotes: cr.registerManagerNotes },\n });\n }\n\n if (CR.isReturnedForClarification(cr)) {\n els.push({\n label: \"Return for clarification\",\n toState: CR.State.RETURNED_FOR_CLARIFICATION,\n input: {\n registerManagerNotes: cr.registerManagerNotes,\n controlBodyNotes: (cr as any).controlBodyNotes,\n controlBodyDecisionEvent: (cr as any).controlBodyDecisionEvent,\n },\n });\n }\n\n if (CR.isWithdrawn(cr)) {\n els.push({\n label: \"Withdraw\",\n toState: CR.State.WITHDRAWN,\n timestamp: cr.timeDisposed,\n });\n } else if (CR.isAccepted(cr)) {\n els.push({\n label: \"Accept\",\n toState: CR.State.ACCEPTED,\n timestamp: cr.timeDisposed,\n input: {\n controlBodyNotes: (cr as any).controlBodyNotes,\n controlBodyDecisionEvent: (cr as any).controlBodyDecisionEvent,\n },\n });\n } else if (CR.isRejected(cr)) {\n els.push({\n label: \"Reject\",\n toState: CR.State.REJECTED,\n timestamp: cr.timeDisposed,\n input: {\n controlBodyNotes: (cr as any).controlBodyNotes,\n controlBodyDecisionEvent: (cr as any).controlBodyDecisionEvent,\n },\n });\n }\n\n if (CR.isAppealed(cr)) {\n els.push({\n label: \"Appeal\",\n toState: CR.State.APPEALED,\n input: {\n appealReason: cr.appealReason,\n },\n });\n }\n\n if (CR.isRejectedWithAppealWithdrawn(cr)) {\n els.push({\n label: \"Withdraw appeal\",\n toState: CR.State.APPEAL_WITHDRAWN,\n timestamp: cr.timeDisposed,\n });\n } else if (CR.isAcceptedOnAppeal(cr)) {\n els.push({\n label: \"Accept on appeal\",\n toState: CR.State.ACCEPTED_ON_APPEAL,\n timestamp: cr.timeDisposed,\n input: {\n registerOwnerNotes: cr.registerOwnerNotes,\n },\n });\n } else if (CR.isRejectedOnAppeal(cr)) {\n els.push({\n label: \"Uphold rejection\",\n toState: CR.State.REJECTION_UPHELD_ON_APPEAL,\n timestamp: cr.timeDisposed,\n input: {\n registerOwnerNotes: cr.registerOwnerNotes,\n },\n });\n }\n return els;\n }\n}\n\n\n/**\n * Lists transitions between states,\n * emphasizing the end (current as of now) state.\n */\nexport const TransitionsAndStatus: React.VoidFunctionComponent<{\n pastTransitions: TransitionHistoryEntry[]\n isFinal?: boolean\n detailed?: boolean\n}> = function ({ pastTransitions, isFinal, detailed }) {\n return (\n <>\n {pastTransitions.map((entry, idx) => {\n if (entry) {\n const { label, stakeholder, fromState, toState, input, timestamp } = entry;\n const details = input || timestamp || stakeholder\n ? <>\n {input\n ? <div css={css`margin: .25em 0;`}><Val val={normalizeObjectRecursively(input)} /></div>\n : null}\n <small css={css`display: block;`}>\n {stakeholder\n ? <span>{registerStakeholderPlain(stakeholder)}</span>\n : 'unknown stakeholder'}\n <br />\n at {timestamp\n ? (timestamp.toISOString?.() || timestamp)\n : 'unknown time'}\n </small>\n </>\n : null;\n return <TransitionEntryWrapper\n title={`Transition ${fromState ? `from ${fromState} ` : ''}to ${toState}`}\n css={css`\n background: linear-gradient(\n 345deg,\n ${STATE_COLOR[toState] ?? Colors.GRAY1}aa,\n ${STATE_COLOR[toState] ?? Colors.GRAY1} 50%);\n position: sticky;\n top: ${idx * 3}px;\n z-index: 1;\n ${idx === pastTransitions.length - 1\n ? `\n ${!detailed ? 'font-weight: bold;' : ''}\n ${isFinal\n ? `\n &::before {\n ${transitionEntryDecorativeMarkerFinal}\n }\n `\n : ''}\n `\n : ''}\n ${idx === 0\n ? `\n &::before {\n ${transitionEntryDecorativeMarkerInitial}\n }\n `\n : ''}\n `}\n key={idx}>\n {label}\n {detailed && details ? details : null}\n {!detailed && details\n ? <> <HelpTooltip icon=\"info-sign\" content={<div css={css`display: flex; flex-flow: column nowrap;`}>{details}</div>} />\n </>\n : null}\n </TransitionEntryWrapper>\n } else {\n if (idx > 0 && pastTransitions[idx - 1] !== undefined) {\n return <MissingTransitionEntries />;\n } else {\n // Don’t output multiple missing steps in a row.\n return null;\n }\n }\n })}\n </>\n );\n};\n\n\n/** Shown in place of transition entries, if some are missing. */\nconst MissingTransitionEntries: React.VoidFunctionComponent<Record<never, never>> = function () {\n return (\n <div title=\"No detailed state transitions available\">\n <Icon\n icon=\"more\"\n css={css`\n position: relative;\n left: ${TRANSITION_ENTRY_MARKER_SIDE_OFFSET_PX}px;\n transform: translateX(-50%);\n `}\n />\n </div>\n );\n};\n\n\nconst TRANSITION_ENTRY_MARKER_SIDE_OFFSET_PX = 22;\n\n/**\n * Style rules for pseudo-element that contains decorative marker line with a circle.\n */\nconst transitionEntryDecorativeMarker = `\n content: \" \";\n background: white;\n display: block;\n overflow: hidden;\n z-index: 1;\n position: absolute;\n left: ${TRANSITION_ENTRY_MARKER_SIDE_OFFSET_PX}px;\n\n transform: translateX(-50%);\n top: 0;\n width: 2px;\n bottom: 0;\n`;\n\n/**\n * Style rules for pseudo-element that contains decorative marker line with a circle.\n */\nconst transitionEntryDecorativeMarkerInitial = `\n top: 50%;\n`;\n\n/**\n * Style rules for pseudo-element that contains decorative marker line with a circle.\n */\nconst transitionEntryDecorativeMarkerFinal = `\n bottom: 50%;\n`;\n\n\nconst TransitionEntryWrapper = styled.div`\n position: relative;\n color: white;\n padding: 10px;\n padding-left: ${TRANSITION_ENTRY_MARKER_SIDE_OFFSET_PX + 20}px;\n margin-bottom: 1px;\n\n &::after {\n content: \" \";\n background: white;\n display: block;\n overflow: hidden;\n z-index: 1;\n position: absolute;\n left: ${TRANSITION_ENTRY_MARKER_SIDE_OFFSET_PX}px;\n\n transform: translateX(-50%) translateY(-50%);\n top: 50%;\n width: 10px;\n height: 10px;\n border-radius: 100%;\n }\n\n &::before {\n ${transitionEntryDecorativeMarker}\n }\n`;\n\n\nexport default TransitionsAndStatus;\n"]}
|
|
1
|
+
{"version":3,"file":"TransitionHistory.js","sourceRoot":"","sources":["../../src/proposals/TransitionHistory.tsx"],"names":[],"mappings":"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","sourcesContent":["/** @jsx jsx */\n/** @jsxFrag React.Fragment */\n\nimport styled from '@emotion/styled';\nimport { jsx, css } from '@emotion/react';\nimport React from 'react';\nimport { Icon, Colors } from '@blueprintjs/core';\n\nimport { normalizeObjectRecursively } from '@riboseinc/paneron-extension-kit/util';\nimport HelpTooltip from '@riboseinc/paneron-extension-kit/widgets/HelpTooltip';\n\nimport { Val } from '../views/diffing/InlineDiff';\nimport { Datestamp } from '../views/util';\nimport { registerStakeholderPlain } from '../views/RegisterStakeholder';\nimport { type RegisterStakeholder } from '../types/stakeholder';\n\nimport * as CR from './types';\nimport { STATE_COLOR } from './TransitionOptions';\n\n\n/**\n * Transition history entry is mostly like `CR.TransitionEntry`,\n * except it has optional fields and can be `undefined` to represent\n * missing parts of history.\n */\nexport type TransitionHistoryEntry = Omit<CR.TransitionEntry, 'timestamp' | 'fromState' | 'stakeholder' | 'input'> & {\n timestamp?: Date\n fromState?: CR.StateType\n stakeholder?: RegisterStakeholder\n input?: CR.StateInput\n} | undefined;\n\n\n/**\n * Outputs transition history,\n * back-filling it from state and timestamps if `pastTransitions` is not present.\n */\nexport function getTransitionHistory(cr: CR.Base): TransitionHistoryEntry[] {\n if (cr.pastTransitions && cr.pastTransitions.length > 0) {\n return [{\n label: \"Create\",\n toState: CR.State.DRAFT,\n timestamp: (cr as CR.Drafted).timeStarted,\n }, ...cr.pastTransitions];\n\n } else {\n const els: TransitionHistoryEntry[] = [];\n\n els.push({\n label: \"Create\",\n toState: CR.State.DRAFT,\n timestamp: (cr as CR.Drafted).timeStarted,\n });\n\n if (!CR.isDrafted(cr)) {\n els.push(undefined);\n }\n\n // Backward compatibility\n\n if (CR.isProposed(cr)) {\n els.push({\n label: \"Propose\",\n toState: CR.State.PROPOSED,\n timestamp: cr.timeProposed,\n input: { justification: cr.justification },\n });\n }\n\n if (CR.isSubmittedForControlBodyReview(cr)) {\n els.push({\n label: \"Submit for control body review\",\n fromState: CR.State.PROPOSED,\n toState: CR.State.SUBMITTED_FOR_CONTROL_BODY_REVIEW,\n input: { registerManagerNotes: cr.registerManagerNotes },\n });\n }\n\n if (CR.isReturnedForClarification(cr)) {\n els.push({\n label: \"Return for clarification\",\n toState: CR.State.RETURNED_FOR_CLARIFICATION,\n input: {\n registerManagerNotes: cr.registerManagerNotes,\n controlBodyNotes: (cr as any).controlBodyNotes,\n controlBodyDecisionEvent: (cr as any).controlBodyDecisionEvent,\n },\n });\n }\n\n if (CR.isWithdrawn(cr)) {\n els.push({\n label: \"Withdraw\",\n toState: CR.State.WITHDRAWN,\n timestamp: cr.timeDisposed,\n });\n } else if (CR.isAccepted(cr)) {\n els.push({\n label: \"Accept\",\n toState: CR.State.ACCEPTED,\n timestamp: cr.timeDisposed,\n input: {\n controlBodyNotes: (cr as any).controlBodyNotes,\n controlBodyDecisionEvent: (cr as any).controlBodyDecisionEvent,\n },\n });\n } else if (CR.isRejected(cr)) {\n els.push({\n label: \"Reject\",\n toState: CR.State.REJECTED,\n timestamp: cr.timeDisposed,\n input: {\n controlBodyNotes: (cr as any).controlBodyNotes,\n controlBodyDecisionEvent: (cr as any).controlBodyDecisionEvent,\n },\n });\n }\n\n if (CR.isAppealed(cr)) {\n els.push({\n label: \"Appeal\",\n toState: CR.State.APPEALED,\n input: {\n appealReason: cr.appealReason,\n },\n });\n }\n\n if (CR.isRejectedWithAppealWithdrawn(cr)) {\n els.push({\n label: \"Withdraw appeal\",\n toState: CR.State.APPEAL_WITHDRAWN,\n timestamp: cr.timeDisposed,\n });\n } else if (CR.isAcceptedOnAppeal(cr)) {\n els.push({\n label: \"Accept on appeal\",\n toState: CR.State.ACCEPTED_ON_APPEAL,\n timestamp: cr.timeDisposed,\n input: {\n registerOwnerNotes: cr.registerOwnerNotes,\n },\n });\n } else if (CR.isRejectedOnAppeal(cr)) {\n els.push({\n label: \"Uphold rejection\",\n toState: CR.State.REJECTION_UPHELD_ON_APPEAL,\n timestamp: cr.timeDisposed,\n input: {\n registerOwnerNotes: cr.registerOwnerNotes,\n },\n });\n }\n return els;\n }\n}\n\n\n/**\n * Lists transitions between states,\n * emphasizing the end (current as of now) state.\n */\nexport const TransitionsAndStatus: React.VoidFunctionComponent<{\n pastTransitions: TransitionHistoryEntry[]\n isFinal?: boolean\n detailed?: boolean\n}> = function ({ pastTransitions, isFinal, detailed }) {\n return (\n <>\n {pastTransitions.map((entry, idx) => {\n if (entry) {\n const { label, stakeholder, fromState, toState, input, timestamp } = entry;\n const details = input || timestamp || stakeholder\n ? <>\n {input\n ? <div css={css`margin: .25em 0;`}>\n <Val val={normalizeObjectRecursively(input)} />\n </div>\n : null}\n <small css={css`display: block;`}>\n {stakeholder\n ? <span>{registerStakeholderPlain(stakeholder)}</span>\n : 'unknown stakeholder'}\n <br />\n at {timestamp\n ? <Datestamp useUTC showTime date={timestamp} />\n : \"unknown time\"}\n </small>\n </>\n : null;\n return <TransitionEntryWrapper\n title={`Transition ${fromState ? `from ${fromState} ` : ''}to ${toState}`}\n css={css`\n background: linear-gradient(\n 345deg,\n ${STATE_COLOR[toState] ?? Colors.GRAY1}aa,\n ${STATE_COLOR[toState] ?? Colors.GRAY1} 50%);\n position: sticky;\n top: ${idx * 3}px;\n z-index: 1;\n ${idx === pastTransitions.length - 1\n ? `\n ${!detailed ? 'font-weight: bold;' : ''}\n ${isFinal\n ? `\n &::before {\n ${transitionEntryDecorativeMarkerFinal}\n }\n `\n : ''}\n `\n : ''}\n ${idx === 0\n ? `\n &::before {\n ${transitionEntryDecorativeMarkerInitial}\n }\n `\n : ''}\n `}\n key={idx}>\n {label}\n {detailed && details ? details : null}\n {!detailed && details\n ? <> <HelpTooltip icon=\"info-sign\" content={<div css={css`display: flex; flex-flow: column nowrap;`}>{details}</div>} />\n </>\n : null}\n </TransitionEntryWrapper>\n } else {\n if (idx > 0 && pastTransitions[idx - 1] !== undefined) {\n return <MissingTransitionEntries />;\n } else {\n // Don’t output multiple missing steps in a row.\n return null;\n }\n }\n })}\n </>\n );\n};\n\n\n/** Shown in place of transition entries, if some are missing. */\nconst MissingTransitionEntries: React.VoidFunctionComponent<Record<never, never>> = function () {\n return (\n <div title=\"No detailed state transitions available\">\n <Icon\n icon=\"more\"\n css={css`\n position: relative;\n left: ${TRANSITION_ENTRY_MARKER_SIDE_OFFSET_PX}px;\n transform: translateX(-50%);\n `}\n />\n </div>\n );\n};\n\n\nconst TRANSITION_ENTRY_MARKER_SIDE_OFFSET_PX = 22;\n\n/**\n * Style rules for pseudo-element that contains decorative marker line with a circle.\n */\nconst transitionEntryDecorativeMarker = `\n content: \" \";\n background: white;\n display: block;\n overflow: hidden;\n z-index: 1;\n position: absolute;\n left: ${TRANSITION_ENTRY_MARKER_SIDE_OFFSET_PX}px;\n\n transform: translateX(-50%);\n top: 0;\n width: 2px;\n bottom: 0;\n`;\n\n/**\n * Style rules for pseudo-element that contains decorative marker line with a circle.\n */\nconst transitionEntryDecorativeMarkerInitial = `\n top: 50%;\n`;\n\n/**\n * Style rules for pseudo-element that contains decorative marker line with a circle.\n */\nconst transitionEntryDecorativeMarkerFinal = `\n bottom: 50%;\n`;\n\n\nconst TransitionEntryWrapper = styled.div`\n position: relative;\n color: white;\n padding: 10px;\n padding-left: ${TRANSITION_ENTRY_MARKER_SIDE_OFFSET_PX + 20}px;\n margin-bottom: 1px;\n\n &::after {\n content: \" \";\n background: white;\n display: block;\n overflow: hidden;\n z-index: 1;\n position: absolute;\n left: ${TRANSITION_ENTRY_MARKER_SIDE_OFFSET_PX}px;\n\n transform: translateX(-50%) translateY(-50%);\n top: 50%;\n width: 10px;\n height: 10px;\n border-radius: 100%;\n }\n\n &::before {\n ${transitionEntryDecorativeMarker}\n }\n`;\n\n\nexport default TransitionsAndStatus;\n"]}
|
|
@@ -188,6 +188,21 @@ const ActionableCRTree = function ({
|
|
|
188
188
|
return (0, _react2.jsx)(_core.Tree, {
|
|
189
189
|
className: className,
|
|
190
190
|
contents: nodes,
|
|
191
|
+
css: (0, _react2.css)`
|
|
192
|
+
.bp4-tree-node {
|
|
193
|
+
&.tree-node-active-proposal, &.tree-node-proposal-group-with-active-proposal:not(.bp4-tree-node-expanded) {
|
|
194
|
+
> .bp4-tree-node-content {
|
|
195
|
+
background: ${_core.Colors.RED5};
|
|
196
|
+
.bp4-dark & {
|
|
197
|
+
background: ${_core.Colors.RED2};
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
&.bp4-tree-node-selected > .bp4-tree-node-content {
|
|
201
|
+
background: ${_core.Colors.RED3};
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
`,
|
|
191
206
|
...eventHandlers
|
|
192
207
|
});
|
|
193
208
|
};
|
|
@@ -1 +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, useCallback, 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 { TabbedWorkspaceContext } from '@riboseinc/paneron-extension-kit/widgets/TabbedWorkspace/context';\nimport type { PersistentStateReducerHook } from '@riboseinc/paneron-extension-kit/usePersistentStateReducer';\nimport type { SomeCR as CR } from '../types';\nimport { ChangeRequestContext } from '../ChangeRequestContext';\nimport { BrowserCtx } from '../../views/BrowserCtx';\nimport { getActionableProposalGroupsForRoles } from './queries';\nimport { Protocols } from '../../views/protocolRegistry';\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 const { spawnTab } = useContext(TabbedWorkspaceContext);\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 onActivateCR: setActiveChangeRequestID,\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, setActiveChangeRequestID, actionableProposals, state.selectedItemID, state.expandedFolderIDs.join(',')]);\n\n const activate = useCallback(((proposalID: string) => {\n if (proposalID !== activeCR?.id) {\n setActiveChangeRequestID?.(proposalID as string)\n }\n // open proposal dashboard regardless\n spawnTab(Protocols.PROPOSAL_WORK, { atIdx: 0 });\n }), [activeCR?.id, setActiveChangeRequestID, spawnTab]);\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 : activate(node.id as string),\n })), [dispatch, activate]);\n\n return <Tree\n className={className}\n contents={nodes}\n {...eventHandlers}\n />;\n}\n\nexport default ActionableCRTree;\n"]}
|
|
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, useCallback, useMemo } from 'react';\nimport update from 'immutability-helper';\nimport { jsx, css } from '@emotion/react';\nimport { Colors, Tree } from '@blueprintjs/core';\nimport { DatasetContext } from '@riboseinc/paneron-extension-kit';\nimport { TabbedWorkspaceContext } from '@riboseinc/paneron-extension-kit/widgets/TabbedWorkspace/context';\nimport type { PersistentStateReducerHook } from '@riboseinc/paneron-extension-kit/usePersistentStateReducer';\nimport type { SomeCR as CR } from '../types';\nimport { ChangeRequestContext } from '../ChangeRequestContext';\nimport { BrowserCtx } from '../../views/BrowserCtx';\nimport { getActionableProposalGroupsForRoles } from './queries';\nimport { Protocols } from '../../views/protocolRegistry';\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 const { spawnTab } = useContext(TabbedWorkspaceContext);\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 onActivateCR: setActiveChangeRequestID,\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, setActiveChangeRequestID, actionableProposals, state.selectedItemID, state.expandedFolderIDs.join(',')]);\n\n const activate = useCallback(((proposalID: string) => {\n if (proposalID !== activeCR?.id) {\n setActiveChangeRequestID?.(proposalID as string)\n }\n // open proposal dashboard regardless\n spawnTab(Protocols.PROPOSAL_WORK, { atIdx: 0 });\n }), [activeCR?.id, setActiveChangeRequestID, spawnTab]);\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 : activate(node.id as string),\n })), [dispatch, activate]);\n\n return <Tree\n className={className}\n contents={nodes}\n css={css`\n .bp4-tree-node {\n &.tree-node-active-proposal, &.tree-node-proposal-group-with-active-proposal:not(.bp4-tree-node-expanded) {\n > .bp4-tree-node-content {\n background: ${Colors.RED5};\n .bp4-dark & {\n background: ${Colors.RED2};\n }\n }\n &.bp4-tree-node-selected > .bp4-tree-node-content {\n background: ${Colors.RED3};\n }\n }\n }\n `}\n {...eventHandlers}\n />;\n}\n\nexport default ActionableCRTree;\n"]}
|
|
@@ -38,11 +38,13 @@ function getActionableProposalGroupsAsTreeNodes(groups, opts) {
|
|
|
38
38
|
id: groupLabel,
|
|
39
39
|
label: groupLabel,
|
|
40
40
|
hasCaret: true,
|
|
41
|
+
className: hasActiveProposal ? 'tree-node-proposal-group-with-active-proposal' : undefined,
|
|
41
42
|
secondaryLabel: hasActiveProposal && !isExpanded ? (0, _react2.jsx)(ActiveMarker, {
|
|
42
|
-
isActive: true
|
|
43
|
+
isActive: true,
|
|
44
|
+
title: "A proposal in this group is currently active, expand group to see it"
|
|
43
45
|
}) : (0, _react2.jsx)(_core.Tag, {
|
|
44
46
|
minimal: !hasProposals,
|
|
45
|
-
intent: hasProposals ? '
|
|
47
|
+
intent: hasProposals ? 'warning' : undefined
|
|
46
48
|
}, hasProposals ? proposals.length : 0),
|
|
47
49
|
icon: isExpanded ? 'folder-open' : 'folder-close',
|
|
48
50
|
isExpanded,
|
|
@@ -61,6 +63,7 @@ function getActionableProposalGroupsAsTreeNodes(groups, opts) {
|
|
|
61
63
|
|
|
62
64
|
const ActiveMarker = function ({
|
|
63
65
|
onToggle,
|
|
66
|
+
title,
|
|
64
67
|
isActive
|
|
65
68
|
}) {
|
|
66
69
|
const handleClick = (0, _react.useCallback)(evt => {
|
|
@@ -70,9 +73,9 @@ const ActiveMarker = function ({
|
|
|
70
73
|
return (0, _react2.jsx)(_core.Button, {
|
|
71
74
|
icon: "eye-open",
|
|
72
75
|
small: true,
|
|
73
|
-
|
|
76
|
+
title: title !== null && title !== void 0 ? title : onToggle ? isActive ? "Click to deactivate (exit) this proposal" : "Click to activate this proposal" : undefined,
|
|
74
77
|
active: isActive,
|
|
75
|
-
intent: isActive ? 'danger' :
|
|
78
|
+
intent: isActive ? 'danger' : 'primary',
|
|
76
79
|
disabled: !onToggle,
|
|
77
80
|
onClick: handleClick
|
|
78
81
|
});
|
|
@@ -84,10 +87,11 @@ function getActionableProposalTreeNode(proposal, opts) {
|
|
|
84
87
|
return {
|
|
85
88
|
id: proposal.id,
|
|
86
89
|
label: (0, _react2.jsx)("span", {
|
|
87
|
-
title:
|
|
90
|
+
title: `“${proposal.justification}” — double-click to open & activate this proposal`
|
|
88
91
|
}, proposal.justification),
|
|
89
92
|
isSelected: (_a = opts === null || opts === void 0 ? void 0 : opts.isSelected) !== null && _a !== void 0 ? _a : false,
|
|
90
93
|
icon: 'lightbulb',
|
|
94
|
+
className: (opts === null || opts === void 0 ? void 0 : opts.isActive) ? 'tree-node-active-proposal' : undefined,
|
|
91
95
|
secondaryLabel: (opts === null || opts === void 0 ? void 0 : opts.isActive) ? (0, _react2.jsx)(ActiveMarker, {
|
|
92
96
|
isActive: true,
|
|
93
97
|
onToggle: opts.onActivateCR ? () => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"treeNodes.js","sourceRoot":"","sources":["../../../src/proposals/actionableGroups/treeNodes.tsx"],"names":[],"mappings":"AAAA,eAAe;AACf,8BAA8B;AAE9B;;;GAGG;AAEH,OAAc,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AAC3C,OAAO,EAAE,GAAG,EAAE,MAAM,gBAAgB,CAAC;AAErC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,mBAAmB,CAAC;AAKhD,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAU3C,MAAM,UAAU,sCAAsC,CACpD,MAAgD,EAChD,IAMC;IAED,OAAO,MAAM;QACX,+DAA+D;QAC/D,GAAG,CAAC,CAAC,EAAE,UAAU,EAAE,SAAS,EAAE,EAAE,EAAE;;QAChC,MAAM,YAAY,GAAG,SAAS,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC;QACvD,MAAM,iBAAiB,GAAG,YAAY;gBACjC,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,UAAU,CAAA,IAAI,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,IAAI,CAAC,UAAU,CAAC,CAAC;QACvE,MAAM,mBAAmB,GAAG,YAAY;gBACnC,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,YAAY,CAAA,IAAI,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,IAAI,CAAC,YAAY,CAAC,CAAC;QAC3E,MAAM,UAAU,GACd,MAAM,CAAC,MAAM,KAAK,CAAC;gBAChB,MAAA,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,mBAAmB,0CAAE,GAAG,CAAC,UAAU,CAAC,CAAA;eAC1C,mBAAmB;YACpB,CAAC,CAAC,IAAI;YACN,CAAC,CAAC,KAAK,CAAC;QAEZ,OAAO;YACL,EAAE,EAAE,UAAU;YACd,KAAK,EAAE,UAAU;YACjB,QAAQ,EAAE,IAAI;YACd,cAAc,EACZ,iBAAiB,IAAI,CAAC,UAAU;gBAC9B,CAAC,CAAC,IAAC,YAAY,
|
|
1
|
+
{"version":3,"file":"treeNodes.js","sourceRoot":"","sources":["../../../src/proposals/actionableGroups/treeNodes.tsx"],"names":[],"mappings":"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","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\nimport React, { useCallback } from 'react';\nimport { jsx } from '@emotion/react';\n\nimport { Button, Tag } from '@blueprintjs/core';\nimport type { IconName, TreeNodeInfo } from '@blueprintjs/core';\nimport type { RegisterStakeholder } from '../../types';\nimport type { SomeCR as CR } from '../types';\nimport type { ActionableProposalGroup } from './types';\nimport { CR_BASE_QUERY } from '../queries';\n\n\nexport type ActionableProposalTreeNode = TreeNodeInfo<{ type: 'group' | 'item' }>;\n\n\ninterface ActionableProposalGroupResult {\n groupLabel: string\n proposals: CR[] | undefined\n}\nexport function getActionableProposalGroupsAsTreeNodes(\n groups: readonly ActionableProposalGroupResult[],\n opts?: {\n expandedGroupLabels?: Set<string>\n selectedGroup?: string\n selectedCRID?: string\n activeCRID?: string\n onActivateCR?: (crID: string | null) => void | Promise<void>\n },\n): ActionableProposalTreeNode[] {\n return groups.\n //filter(({ proposals }) => proposals && proposals.length > 0).\n map(({ groupLabel, proposals }) => {\n const hasProposals = proposals && proposals.length > 0;\n const hasActiveProposal = hasProposals\n && opts?.activeCRID && proposals.find(p => p.id === opts.activeCRID);\n const hasSelectedProposal = hasProposals\n && opts?.selectedCRID && proposals.find(p => p.id === opts.selectedCRID);\n const isExpanded =\n groups.length === 1\n || opts?.expandedGroupLabels?.has(groupLabel)\n || hasSelectedProposal\n ? true\n : false;\n\n return {\n id: groupLabel,\n label: groupLabel,\n hasCaret: true,\n className: hasActiveProposal\n ? 'tree-node-proposal-group-with-active-proposal'\n : undefined,\n secondaryLabel:\n hasActiveProposal && !isExpanded\n ? <ActiveMarker\n isActive\n title=\"A proposal in this group is currently active, expand group to see it\"\n />\n : <Tag\n minimal={!hasProposals}\n intent={hasProposals ? 'warning' : undefined}>\n {hasProposals ? proposals.length : 0}\n </Tag>,\n icon: isExpanded\n ? 'folder-open'\n : 'folder-close' as IconName,\n isExpanded,\n isSelected: groupLabel === opts?.selectedGroup,\n nodeData: { type: 'group' },\n childNodes: hasProposals && isExpanded\n ? proposals.map(p => getActionableProposalTreeNode(p, {\n isSelected: p.id === opts?.selectedCRID,\n isActive: p.id === opts?.activeCRID,\n onActivateCR: opts?.onActivateCR,\n }))\n : [],\n };\n });\n}\n\nconst ActiveMarker: React.FC<{\n isActive?: boolean\n onToggle?: () => void\n title?: string\n}> = function ({ onToggle, title, isActive }) {\n const handleClick = useCallback(\n ((evt: React.MouseEvent<any>) => {\n evt.stopPropagation();\n onToggle?.();\n }),\n [onToggle]);\n return <Button\n icon=\"eye-open\"\n small\n title={title ?? (onToggle\n ? isActive\n ? \"Click to deactivate (exit) this proposal\"\n : \"Click to activate this proposal\"\n : undefined)}\n active={isActive}\n intent={isActive ? 'danger' : 'primary'}\n disabled={!onToggle}\n onClick={handleClick}\n />\n};\n\n\nfunction getActionableProposalTreeNode(\n proposal: CR,\n opts?: {\n isSelected?: boolean\n isActive?: boolean\n onActivateCR?: (crID: string | null) => void\n },\n): ActionableProposalTreeNode {\n return {\n id: proposal.id,\n label: <span title={`“${proposal.justification}” — double-click to open & activate this proposal`}>\n {proposal.justification}\n </span>,\n isSelected: opts?.isSelected ?? false,\n icon: 'lightbulb',\n className: opts?.isActive\n ? 'tree-node-active-proposal'\n : undefined,\n secondaryLabel: opts?.isActive\n ? <ActiveMarker isActive onToggle={opts.onActivateCR ? () => opts?.onActivateCR?.(null) : undefined} />\n : <ActiveMarker onToggle={opts?.onActivateCR ? () => opts?.onActivateCR?.(proposal.id) : undefined} />,\n nodeData: { type: 'item' },\n };\n}\n\n\nexport function getMapReduceChainsForActionableProposalGroups(\n proposalGroups: readonly ActionableProposalGroup[],\n stakeholder: RegisterStakeholder,\n) {\n return proposalGroups.map(([label, , queryGetter]) => {\n const query = queryGetter(stakeholder);\n const predicateFunc = `\n const objPath = key, obj = value;\n return ((${CR_BASE_QUERY}) && (${query}));\n `;\n const mapFunc = `emit(value);`;\n return { [label]: { mapFunc, predicateFunc } };\n }).reduce((prev, curr) => ({ ...prev, ...curr }), {});\n}\n"]}
|
package/proposals/types.d.ts
CHANGED
|
@@ -169,6 +169,7 @@ export declare function isWithdrawn(cr: Base): cr is Withdrawn;
|
|
|
169
169
|
export declare function hadBeenProposed(cr: Base): cr is Base & {
|
|
170
170
|
timeProposed: Date;
|
|
171
171
|
};
|
|
172
|
+
export declare function hadBeenAccepted(cr: Base): cr is Accepted | AcceptedOnAppeal;
|
|
172
173
|
/** A proposal that had been disposed is not pending, not actionable. */
|
|
173
174
|
export declare function isDisposed(cr: Base): cr is Base & {
|
|
174
175
|
timeDisposed: Date;
|
package/proposals/types.js
CHANGED
|
@@ -23,6 +23,7 @@ exports.isDrafted = isDrafted;
|
|
|
23
23
|
exports.isProposed = isProposed;
|
|
24
24
|
exports.isWithdrawn = isWithdrawn;
|
|
25
25
|
exports.hadBeenProposed = hadBeenProposed;
|
|
26
|
+
exports.hadBeenAccepted = hadBeenAccepted;
|
|
26
27
|
exports.isDisposed = isDisposed;
|
|
27
28
|
exports.isSubmittedForControlBodyReview = isSubmittedForControlBodyReview;
|
|
28
29
|
exports.isReturnedForClarification = isReturnedForClarification;
|
|
@@ -182,6 +183,10 @@ function isWithdrawn(cr) {
|
|
|
182
183
|
function hadBeenProposed(cr) {
|
|
183
184
|
return cr && cr.hasOwnProperty('timeProposed') && !!cr.timeProposed;
|
|
184
185
|
}
|
|
186
|
+
|
|
187
|
+
function hadBeenAccepted(cr) {
|
|
188
|
+
return isDisposed(cr) && (isAccepted(cr) || isAcceptedOnAppeal(cr));
|
|
189
|
+
}
|
|
185
190
|
/** A proposal that had been disposed is not pending, not actionable. */
|
|
186
191
|
|
|
187
192
|
|
package/proposals/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/proposals/types.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Proposals, group proposals,\n * group proposal states and state transitions.\n */\n\nimport type React from 'react';\nimport type { DatasetContext } from '@riboseinc/paneron-extension-kit/types/renderer';\n\nimport type {\n InternalItemReference,\n Payload,\n RegisterItem,\n} from '../types';\n\nimport type { RegisterStakeholder } from '../types/stakeholder';\nimport type { Citation } from '../types/util';\n\n\n// Proposal items\n// ==============\n\n/**\n * Item paths in proposal set must start with a slash\n * and will be treated relative to dataset root.\n * Object paths should conform to registry item path shape\n * of `/<classID>/<itemID>.yaml`.\n * (the `[/subregisterID]/<classID>/<itemID>.yaml` is acceptable\n * but deprecated, as subregisters are deprecated).\n */\nexport type ProposalSet = {\n [objectPath: string]: ChangeProposal\n}\n\nexport const ChangeProposalType = {\n ADDITION: 'addition',\n CLARIFICATION: 'clarification',\n AMENDMENT: 'amendment',\n} as const;\nexport const PROPOSAL_TYPES = [\n ChangeProposalType.ADDITION,\n ChangeProposalType.CLARIFICATION,\n ChangeProposalType.AMENDMENT,\n] as const;\n\ninterface BaseProposal {\n //itemID: RegisterItemID\n disposition?: 'accepted' | 'notAccepted'\n type: typeof PROPOSAL_TYPES[number]\n sources?: Citation[]\n}\n\nexport interface Addition extends BaseProposal {\n type: typeof ChangeProposalType.ADDITION\n ///** New item data. */\n //payload: Payload\n}\n\nexport interface Clarification extends BaseProposal {\n type: typeof ChangeProposalType.CLARIFICATION\n ///** Updated item data */\n //payload: Payload\n}\n\nexport const AmendmentType = {\n SUPERSESSION: 'supersession',\n RETIREMENT: 'retirement',\n INVALIDATION: 'invalidation',\n} as const;\nexport type AmendmentTypeType = typeof AmendmentType[keyof typeof AmendmentType];\nexport const AMENDMENT_TYPES = [\n AmendmentType.SUPERSESSION,\n AmendmentType.RETIREMENT,\n AmendmentType.INVALIDATION,\n] as const;\n\ninterface BaseAmendment extends BaseProposal {\n type: typeof ChangeProposalType.AMENDMENT\n amendmentType: AmendmentTypeType\n}\nexport interface Retirement extends BaseAmendment {\n amendmentType: typeof AmendmentType.RETIREMENT\n}\nexport interface Supersession extends BaseAmendment {\n amendmentType: typeof AmendmentType.SUPERSESSION\n supersedingItemIDs: string[]\n}\nexport interface Invalidation extends BaseAmendment {\n amendmentType: typeof AmendmentType.INVALIDATION\n}\nexport type Amendment = Supersession | Retirement | Invalidation\n\nexport type ChangeProposal = Amendment | Clarification | Addition\n\nexport function isBaseProposal(val: any): val is BaseProposal {\n return PROPOSAL_TYPES.indexOf(val?.type) >= 0;\n}\nexport function isProposal(val: any): val is ChangeProposal {\n return (isBaseProposal(val) && (\n isAddition(val)\n || isClarification(val)\n || isAmendment(val)));\n}\nexport function isAddition(val: BaseProposal): val is Addition {\n return (val.type === ChangeProposalType.ADDITION);\n}\nexport function isClarification(val: BaseProposal): val is Clarification {\n return (val.type === ChangeProposalType.CLARIFICATION);\n}\nexport function isBaseAmendment(val: BaseProposal): val is BaseAmendment {\n return (\n val.type === ChangeProposalType.AMENDMENT\n && AMENDMENT_TYPES.indexOf((val as Amendment).amendmentType) >= 0);\n}\nexport function isAmendment(val: any): val is Amendment {\n return (isBaseAmendment(val) && (\n isRetirement(val)\n || isSupersession(val)\n || isInvalidation(val)));\n}\nexport function isRetirement(val: BaseAmendment): val is Retirement {\n return val.amendmentType === AmendmentType.RETIREMENT;\n}\nexport function isSupersession(val: BaseAmendment): val is Supersession {\n return val.amendmentType === AmendmentType.SUPERSESSION;\n}\nexport function isInvalidation(val: BaseAmendment): val is Invalidation {\n return val.amendmentType === AmendmentType.INVALIDATION;\n}\n\n\n// Change request types, states and state transitions.\n\nexport function isSubmittedBy(stakeholder: RegisterStakeholder, cr: Base): boolean {\n return (\n //isSubmitter(stakeholder) &&\n stakeholder.gitServerUsername === cr.submittingStakeholderGitServerUsername);\n}\n\n\ntype ItemDataset = Record<string, RegisterItem<any> | null>;\n\n\n// =====================\n// Change request states\n// =====================\n\n/** Used in place of enum for convenience. */\nexport const State = {\n DRAFT: 'draft',\n PROPOSED: 'proposed',\n SUBMITTED_FOR_CONTROL_BODY_REVIEW: 'pending-control-body-review',\n RETURNED_FOR_CLARIFICATION: 'returned-for-clarification',\n WITHDRAWN: 'withdrawn',\n ACCEPTED: 'accepted',\n REJECTED: 'rejected',\n APPEALED: 'rejection-appealed-to-owner',\n ACCEPTED_ON_APPEAL: 'accepted-on-appeal',\n REJECTION_UPHELD_ON_APPEAL: 'rejection-upheld-on-appeal',\n APPEAL_WITHDRAWN: 'appeal-withdrawn',\n} as const;\n\nexport type StateType = typeof State[keyof typeof State];\n\nexport function isState(val: string): val is StateType {\n return Object.values(State).indexOf(val as StateType) >= 0;\n}\n\n/** A subset of `State` that represents editable states. */\nexport const EditableState = [\n State.DRAFT,\n State.RETURNED_FOR_CLARIFICATION,\n] as const;\n\nexport type EditableStateType = StateType & typeof EditableState[number];\n\nexport function isEditableState(state: StateType): state is EditableStateType {\n return EditableState.indexOf(state as EditableStateType) >= 0;\n}\n\n\n\n// ======================\n// Change request classes\n// ======================\n\n/**\n * Base change request type.\n *\n * Note that e.g. type Base<typeof State.DRAFT> does not equal to Drafted\n * because Drafted includes additional information (namely, SubmitterInput).\n *\n * If the state of a CR matters, this type should not be used directly\n * and concrete types should be used instead.\n */\nexport interface Base<S extends StateType = StateType>\n{\n id: string;\n // decision: typeof Decision[keyof typeof Decision]\n // disposition?: typeof Disposition[keyof typeof Disposition]\n state: S;\n\n /**\n * Used to match against stakeholders declared in register metadata.\n */\n submittingStakeholderGitServerUsername: string;\n\n items: ProposalSet;\n\n /**\n * Against which register version changes were proposed.\n */\n registerVersion: string;\n\n /**\n * A link to external discussion.\n */\n externalDiscussionURI?: string;\n\n pastTransitions?: TransitionEntry[];\n}\n\n\nexport interface TransitionEntry {\n /** Verb in past tense. */\n label: string;\n\n timestamp: Date;\n fromState: StateType;\n toState: StateType;\n stakeholder: RegisterStakeholder;\n input: StateInput;\n}\n\n\nexport function isCreatedBy(stakeholder: RegisterStakeholder, cr: Base): boolean {\n return stakeholder.gitServerUsername?.trim() !== '' && stakeholder.gitServerUsername === cr.submittingStakeholderGitServerUsername;\n}\n\n/** Whether given `cr` can be edited (as in, items changed) by specified stakeholder. */\nexport function canBeEditedBy(stakeholder: RegisterStakeholder, cr: Base): boolean {\n return isCreatedBy(stakeholder, cr) && isEditableState(cr.state);\n}\n\n/**\n * Whether given `cr` can be deleted by given stakeholder.\n * Unlike editing, deletion is possible only if there are no items\n * and CR was never proposed.\n */\nexport function canBeDeletedBy(stakeholder: RegisterStakeholder, cr: Base): boolean {\n return (\n isCreatedBy(stakeholder, cr)\n && isDrafted(cr)\n //&& Object.keys(cr.items).length < 1 // Only allow deleting empty CRs\n && !hadBeenProposed(cr) // If it had been proposed, it should be withdrawn instead.\n );\n}\n\n\n/** Proposal structure for single-file proposal import format. */\nexport interface ImportableCR {\n /** Proposal data. */\n proposalDraft: Drafted,\n /** Register item data for additions & clarifications. */\n itemPayloads: ItemDataset,\n // TODO: Rename ImportableCR.itemPayloads to newItemData\n}\nexport function isImportableCR(val: any): val is ImportableCR {\n // TODO: More complete check\n return (\n val.proposalDraft.id\n && isDrafted(val.proposalDraft as Base)\n && Object.keys(val.itemPayloads).length > 0);\n}\n\n\n/**\n * A change request in any state.\n * Contains a superset of all possible properties, but all optional.\n * XXX: ^^^ This is a lie. Should be changed from | to & with Partial<>?\n */\nexport type SomeCR = \n | Drafted\n | Proposed\n | Withdrawn\n | ReturnedForClarificationByManager\n | SubmittedForControlBodyReview\n | ReturnedForClarificationByControlBody\n | Accepted\n | Rejected\n | RejectionUpheld\n | AcceptedOnAppeal\n | RejectedWithAppealWithdrawn;\n\nexport type Withdrawable =\n | Proposed\n | SubmittedForControlBodyReview\n | ReturnedForClarificationByManager\n | ReturnedForClarificationByControlBody;\n\nexport type Proposable =\n | Drafted\n | ReturnedForClarificationByManager\n | ReturnedForClarificationByControlBody;\n\nexport type SomeEditable =\n | Drafted\n | ReturnedForClarificationByManager\n | ReturnedForClarificationByControlBody;\n\nexport type Disposed =\n | Withdrawn\n | Accepted\n | Rejected\n | AcceptedOnAppeal\n | RejectionUpheld;\n\n\n// More specific change request types.\n// TODO: Refactor to avoid confusiong between current state e.g. Proposed)\n// and type (Proposed, to which all inheriting classes also conform)\n\nexport interface Drafted extends\n SubmitterInput,\n Base<typeof State.DRAFT> { timeStarted: Date, timeEdited: Date }\nexport function isDrafted(cr: Base): cr is Drafted {\n return isInState(cr, State.DRAFT);\n}\n\nexport interface Proposed extends\n Omit<Drafted, 'state'>,\n Base<typeof State.PROPOSED> { timeProposed: Date }\nexport function isProposed(cr: Base): cr is Proposed {\n return isInState(cr, State.PROPOSED);\n}\n\nexport interface Withdrawn extends\n Omit<Withdrawable, 'state'>,\n Base<typeof State.WITHDRAWN> { timeDisposed: Date }\nexport function isWithdrawn(cr: Base): cr is Withdrawn {\n return isInState(cr, State.WITHDRAWN);\n}\n\n/** CR was proposed at least once. */\nexport function hadBeenProposed(cr: Base): cr is Base & { timeProposed: Date } {\n return cr && cr.hasOwnProperty('timeProposed') && !!(cr as Proposed).timeProposed;\n}\n/** A proposal that had been disposed is not pending, not actionable. */\nexport function isDisposed(cr: Base): cr is Base & { timeDisposed: Date } {\n return cr && cr.hasOwnProperty('timeDisposed') && !!(cr as Disposed).timeDisposed;\n // TODO: include status checks, too?\n //return [\n // State.WITHDRAWN,\n // State.ACCEPTED,\n // State.REJECTED,\n // State.REJECTION_UPHELD_ON_APPEAL,\n // State.ACCEPTED_ON_APPEAL,\n //].some(s => cr.state === s);\n}\n\nexport interface SubmittedForControlBodyReview extends\n Omit<Proposed, 'state'>,\n RegisterManagerInput,\n Base<typeof State.SUBMITTED_FOR_CONTROL_BODY_REVIEW> {}\n\nexport function isSubmittedForControlBodyReview(cr: Base): cr is SubmittedForControlBodyReview {\n return isInState(cr, State.SUBMITTED_FOR_CONTROL_BODY_REVIEW)\n}\n\nexport interface ReturnedForClarificationByManager extends\n Omit<Proposed, 'state'>,\n RegisterManagerInput,\n Base<typeof State.RETURNED_FOR_CLARIFICATION> {}\n\nexport interface ReturnedForClarificationByControlBody extends\n Omit<SubmittedForControlBodyReview, 'state'>,\n ControlBodyInput,\n Base<typeof State.RETURNED_FOR_CLARIFICATION> {}\n\nexport function isReturnedForClarification(cr: Base): cr is (ReturnedForClarificationByManager | ReturnedForClarificationByControlBody) {\n return isInState(cr, State.RETURNED_FOR_CLARIFICATION)\n}\n\nexport interface Accepted extends\n Omit<SubmittedForControlBodyReview, 'state'>,\n ControlBodyInput,\n Base<typeof State.ACCEPTED> { timeDisposed: Date }\nexport function isAccepted(cr: Base): cr is Accepted {\n return isInState(cr, State.ACCEPTED);\n}\n\nexport interface Rejected extends\n Omit<SubmittedForControlBodyReview, 'state'>,\n ControlBodyInput,\n Base<typeof State.REJECTED> { timeDisposed: Date }\nexport function isRejected(cr: Base): cr is Rejected {\n return isInState(cr, State.REJECTED);\n}\n\nexport interface Appealed extends\n Omit<Rejected, 'state' | 'timeDisposed'>,\n AppealRequest,\n Base<typeof State.APPEALED> { timeDisposed: undefined }\nexport function isAppealed(cr: Base): cr is Appealed {\n return isInState(cr, State.APPEALED);\n}\n\nexport interface RejectionUpheld extends\n Omit<Appealed, 'state' | 'timeDisposed'>,\n RegisterOwnerInput,\n Base<typeof State.REJECTION_UPHELD_ON_APPEAL> { timeDisposed: Date }\nexport function isRejectedOnAppeal(cr: Base): cr is RejectionUpheld {\n return isInState(cr, State.REJECTION_UPHELD_ON_APPEAL);\n}\n\nexport interface AcceptedOnAppeal extends\n Omit<Appealed, 'state' | 'timeDisposed'>,\n RegisterOwnerInput,\n Base<typeof State.ACCEPTED_ON_APPEAL> { timeDisposed: Date }\nexport function isAcceptedOnAppeal(cr: Base): cr is AcceptedOnAppeal {\n return isInState(cr, State.ACCEPTED_ON_APPEAL);\n}\n\nexport interface RejectedWithAppealWithdrawn extends\n Omit<Appealed, 'state' | 'timeDisposed'>,\n Base<typeof State.APPEAL_WITHDRAWN> { timeDisposed: Date }\nexport function isRejectedWithAppealWithdrawn(cr: Base): cr is RejectedWithAppealWithdrawn {\n return isInState(cr, State.APPEAL_WITHDRAWN);\n}\n\n\n\n// Input required when transitioning to different states\n\nexport interface SubmitterInput {\n justification: string;\n}\nexport function hasSubmitterInput(val: any): val is SubmitterInput {\n return val.hasOwnProperty('justification') && typeof val.justification === 'string';\n}\nexport interface RegisterManagerInput {\n registerManagerNotes: string;\n}\nexport function hasRegisterManagerInput(val: any): val is RegisterManagerInput {\n return val.hasOwnProperty('registerManagerNotes') && typeof val.registerManagerNotes === 'string';\n}\nexport interface ControlBodyInput {\n controlBodyNotes: string;\n controlBodyDecisionEvent: string;\n}\nexport function hasControlBodyInput(val: any): val is ControlBodyInput {\n return (\n val.hasOwnProperty('controlBodyNotes') && typeof val.controlBodyNotes === 'string' &&\n val.hasOwnProperty('controlBodyDecisionEvent') && typeof val.controlBodyDecisionEvent === 'string');\n}\nexport interface AppealRequest {\n appealReason: string;\n}\nexport function hasAppealRequest(val: any): val is AppealRequest {\n return val.hasOwnProperty('appealReason') && typeof val.appealReason === 'string';\n}\nexport interface RegisterOwnerInput {\n registerOwnerNotes: string;\n}\nexport function hasRegisterOwnerInput(val: any): val is RegisterOwnerInput {\n return val.hasOwnProperty('registerOwnerNotes') && typeof val.registerOwnerNotes === 'string';\n}\n\nexport type StateInput =\n | SubmitterInput\n | RegisterManagerInput\n | ControlBodyInput\n | AppealRequest\n | RegisterOwnerInput;\n\n\n/** \n * CR type guard helper.\n * Normally you would not use it directly and instead use\n * more specific is[Type]() helper from this module.\n *\n * Checks CR type using the `state` property.\n * Does not validate other properties.\n *\n * Usage:\n *\n * @example\n * ```ts\n * let someCR;\n * if (isInState<Drafted>(someCR, State.DRAFT)) {\n * // Can assume someCR is Drafted\n * }\n * ```\n *\n * It’ll try to tell you if you mismatch those.\n *\n * @example\n * Will not compile:\n * ```ts\n * let someCR;\n * if (isInState<Drafted>(someCR, State.PROPOSED)) {\n * // Compile error\n * // because State.PROPOSED is not a possible value of Drafted[\"state\"]\n * }\n * ```\n *\n * @example\n * Incorrect usage (do not do this):\n * ```ts\n * let someCR;\n * if (isInState(someCR, State.DRAFT)) {\n * // Can NOT assume someCR is Drafted\n * // The compiler must know the expected concrete CR type\n * }\n * ```\n */\nfunction isInState<CR extends Base>(cr: Base, s: CR[\"state\"]): cr is CR {\n return cr.state === s;\n}\n\n\n\n\n// ===========\n// Transitions\n// ===========\n\n/**\n * A function that transitions CR1 to CR2.\n *\n * The function is declared to return the object\n * without the `state` field, it is set\n * by common wrapper function to reduce duplication.\n */\nexport type Transition<\n /** From CR of this subtype */\n CR1 extends Base,\n /** To CR of this subtype */\n CR2 extends Base,\n /** Using this extra information */\n P extends Record<string, any> | null = null,\n> = (cr: CR1, payload: P) => Omit<CR2, 'state'>;\n\n\nexport type AlterApprovedCR = (\n crID: string,\n proposals: ProposalSet,\n origItemData: ItemDataset,\n newItemData: ItemDataset,\n opts: Pick<DatasetContext, 'getMapReducedData'>,\n) => Promise<{\n proposals: ProposalSet,\n origItemData: ItemDataset,\n newItemData: ItemDataset,\n}>\n\n\n/**\n * Describes a transition.\n *\n * @typeParam CR1: Change request source state type\n * @typeParam CR2: Change request target state type\n * @typeParam P: Extra input needed to transition, if any\n */\nexport interface TransitionConfig<CR1 extends Base, CR2 extends Base, P extends Record<string, any> | null = null> {\n /**\n * Function that implements the transition.\n * Takes a CR in the original state and returns CR in the new state.\n * Additionally, takes appropriate payload, if any, for the transition\n * (e.g., register manager or control body notes).\n *\n * For function implementor:\n *\n * - Function MUST NOT modify CR in place.\n * - Function should throw if submitted payload does not conform to requirements.\n */\n func: Transition<CR1, CR2, P>;\n\n targetState: CR2[\"state\"];\n\n /** Title. Use verb. */\n title: string;\n\n hint?: string | JSX.Element;\n\n /** Widget that can be used to view or enter extra input. */\n Widget: P extends null ? null : React.FC<{ value: P, onChange?: (userInput: P) => void }>;\n\n /**\n * Function that returns true\n * if given stakeholder can perform this transition on given CR.\n */\n canBeTransitionedBy: (stakeholder: RegisterStakeholder, cr: CR1) => boolean;\n}\n\n\n// type TransitionSpec = {\n// [S1 in StateType]?: {\n// [S2 in StateType]?: Transition<Base<S1>, Base<S2>, Record<string, any>>\n// }\n// }\n\n\n/**\n * Source of truth for available transitions.\n * When updating change request business logic,\n * this is the type that should be modified.\n *\n * It will cause compile errors until transition implementation\n * is updated correspondingly.\n */\nexport type Transitions = {\n [State.DRAFT]: {\n // [State.DRAFT]:\n // TransitionConfig<Drafted, Drafted, SubmitterInput>;\n [State.WITHDRAWN]:\n TransitionConfig<Proposed, Withdrawn>;\n [State.PROPOSED]:\n TransitionConfig<Drafted, Proposed, SubmitterInput>;\n };\n [State.PROPOSED]: {\n [State.WITHDRAWN]:\n TransitionConfig<Proposed, Withdrawn>;\n [State.SUBMITTED_FOR_CONTROL_BODY_REVIEW]:\n TransitionConfig<Proposed, SubmittedForControlBodyReview, RegisterManagerInput>;\n [State.RETURNED_FOR_CLARIFICATION]:\n TransitionConfig<Proposed, ReturnedForClarificationByManager, RegisterManagerInput>;\n };\n [State.SUBMITTED_FOR_CONTROL_BODY_REVIEW]: {\n [State.WITHDRAWN]:\n TransitionConfig<SubmittedForControlBodyReview, Withdrawn>;\n [State.RETURNED_FOR_CLARIFICATION]:\n TransitionConfig<SubmittedForControlBodyReview, ReturnedForClarificationByControlBody, ControlBodyInput>;\n [State.REJECTED]:\n TransitionConfig<SubmittedForControlBodyReview, Rejected, ControlBodyInput>;\n [State.ACCEPTED]:\n TransitionConfig<SubmittedForControlBodyReview, Accepted, ControlBodyInput>;\n };\n [State.RETURNED_FOR_CLARIFICATION]: {\n [State.PROPOSED]:\n TransitionConfig<ReturnedForClarificationByManager | ReturnedForClarificationByControlBody, Proposed, SubmitterInput>;\n [State.WITHDRAWN]:\n TransitionConfig<ReturnedForClarificationByManager | ReturnedForClarificationByControlBody, Withdrawn>;\n };\n [State.REJECTED]: {\n [State.APPEALED]:\n TransitionConfig<Rejected, Appealed, AppealRequest>;\n };\n [State.APPEALED]: {\n [State.APPEAL_WITHDRAWN]:\n TransitionConfig<Appealed, RejectedWithAppealWithdrawn>;\n [State.ACCEPTED_ON_APPEAL]:\n TransitionConfig<Appealed, AcceptedOnAppeal, RegisterOwnerInput>;\n [State.REJECTION_UPHELD_ON_APPEAL]:\n TransitionConfig<Appealed, RejectionUpheld, RegisterOwnerInput>;\n };\n}\n\n\n// Utility\n// =======\n\nexport interface ProposalProps<P extends ChangeProposal> {\n proposal: P\n\n /** Highlight changes. */\n showDiff?: boolean\n\n /** In diff mode, only show changed data. (Provisional.) */\n showOnlyChanged?: boolean\n\n itemRef: InternalItemReference\n item: RegisterItem<Payload>\n itemBefore: P extends Clarification ? RegisterItem<Payload> : undefined\n onChange?: (newProposal: P) => void\n}\n"]}
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/proposals/types.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Proposals, group proposals,\n * group proposal states and state transitions.\n */\n\nimport type React from 'react';\nimport type { DatasetContext } from '@riboseinc/paneron-extension-kit/types/renderer';\n\nimport type {\n InternalItemReference,\n Payload,\n RegisterItem,\n} from '../types';\n\nimport type { RegisterStakeholder } from '../types/stakeholder';\nimport type { Citation } from '../types/util';\n\n\n// Proposal items\n// ==============\n\n/**\n * Item paths in proposal set must start with a slash\n * and will be treated relative to dataset root.\n * Object paths should conform to registry item path shape\n * of `/<classID>/<itemID>.yaml`.\n * (the `[/subregisterID]/<classID>/<itemID>.yaml` is acceptable\n * but deprecated, as subregisters are deprecated).\n */\nexport type ProposalSet = {\n [objectPath: string]: ChangeProposal\n}\n\nexport const ChangeProposalType = {\n ADDITION: 'addition',\n CLARIFICATION: 'clarification',\n AMENDMENT: 'amendment',\n} as const;\nexport const PROPOSAL_TYPES = [\n ChangeProposalType.ADDITION,\n ChangeProposalType.CLARIFICATION,\n ChangeProposalType.AMENDMENT,\n] as const;\n\ninterface BaseProposal {\n //itemID: RegisterItemID\n disposition?: 'accepted' | 'notAccepted'\n type: typeof PROPOSAL_TYPES[number]\n sources?: Citation[]\n}\n\nexport interface Addition extends BaseProposal {\n type: typeof ChangeProposalType.ADDITION\n ///** New item data. */\n //payload: Payload\n}\n\nexport interface Clarification extends BaseProposal {\n type: typeof ChangeProposalType.CLARIFICATION\n ///** Updated item data */\n //payload: Payload\n}\n\nexport const AmendmentType = {\n SUPERSESSION: 'supersession',\n RETIREMENT: 'retirement',\n INVALIDATION: 'invalidation',\n} as const;\nexport type AmendmentTypeType = typeof AmendmentType[keyof typeof AmendmentType];\nexport const AMENDMENT_TYPES = [\n AmendmentType.SUPERSESSION,\n AmendmentType.RETIREMENT,\n AmendmentType.INVALIDATION,\n] as const;\n\ninterface BaseAmendment extends BaseProposal {\n type: typeof ChangeProposalType.AMENDMENT\n amendmentType: AmendmentTypeType\n}\nexport interface Retirement extends BaseAmendment {\n amendmentType: typeof AmendmentType.RETIREMENT\n}\nexport interface Supersession extends BaseAmendment {\n amendmentType: typeof AmendmentType.SUPERSESSION\n supersedingItemIDs: string[]\n}\nexport interface Invalidation extends BaseAmendment {\n amendmentType: typeof AmendmentType.INVALIDATION\n}\nexport type Amendment = Supersession | Retirement | Invalidation\n\nexport type ChangeProposal = Amendment | Clarification | Addition\n\nexport function isBaseProposal(val: any): val is BaseProposal {\n return PROPOSAL_TYPES.indexOf(val?.type) >= 0;\n}\nexport function isProposal(val: any): val is ChangeProposal {\n return (isBaseProposal(val) && (\n isAddition(val)\n || isClarification(val)\n || isAmendment(val)));\n}\nexport function isAddition(val: BaseProposal): val is Addition {\n return (val.type === ChangeProposalType.ADDITION);\n}\nexport function isClarification(val: BaseProposal): val is Clarification {\n return (val.type === ChangeProposalType.CLARIFICATION);\n}\nexport function isBaseAmendment(val: BaseProposal): val is BaseAmendment {\n return (\n val.type === ChangeProposalType.AMENDMENT\n && AMENDMENT_TYPES.indexOf((val as Amendment).amendmentType) >= 0);\n}\nexport function isAmendment(val: any): val is Amendment {\n return (isBaseAmendment(val) && (\n isRetirement(val)\n || isSupersession(val)\n || isInvalidation(val)));\n}\nexport function isRetirement(val: BaseAmendment): val is Retirement {\n return val.amendmentType === AmendmentType.RETIREMENT;\n}\nexport function isSupersession(val: BaseAmendment): val is Supersession {\n return val.amendmentType === AmendmentType.SUPERSESSION;\n}\nexport function isInvalidation(val: BaseAmendment): val is Invalidation {\n return val.amendmentType === AmendmentType.INVALIDATION;\n}\n\n\n// Change request types, states and state transitions.\n\nexport function isSubmittedBy(stakeholder: RegisterStakeholder, cr: Base): boolean {\n return (\n //isSubmitter(stakeholder) &&\n stakeholder.gitServerUsername === cr.submittingStakeholderGitServerUsername);\n}\n\n\ntype ItemDataset = Record<string, RegisterItem<any> | null>;\n\n\n// =====================\n// Change request states\n// =====================\n\n/** Used in place of enum for convenience. */\nexport const State = {\n DRAFT: 'draft',\n PROPOSED: 'proposed',\n SUBMITTED_FOR_CONTROL_BODY_REVIEW: 'pending-control-body-review',\n RETURNED_FOR_CLARIFICATION: 'returned-for-clarification',\n WITHDRAWN: 'withdrawn',\n ACCEPTED: 'accepted',\n REJECTED: 'rejected',\n APPEALED: 'rejection-appealed-to-owner',\n ACCEPTED_ON_APPEAL: 'accepted-on-appeal',\n REJECTION_UPHELD_ON_APPEAL: 'rejection-upheld-on-appeal',\n APPEAL_WITHDRAWN: 'appeal-withdrawn',\n} as const;\n\nexport type StateType = typeof State[keyof typeof State];\n\nexport function isState(val: string): val is StateType {\n return Object.values(State).indexOf(val as StateType) >= 0;\n}\n\n/** A subset of `State` that represents editable states. */\nexport const EditableState = [\n State.DRAFT,\n State.RETURNED_FOR_CLARIFICATION,\n] as const;\n\nexport type EditableStateType = StateType & typeof EditableState[number];\n\nexport function isEditableState(state: StateType): state is EditableStateType {\n return EditableState.indexOf(state as EditableStateType) >= 0;\n}\n\n\n\n// ======================\n// Change request classes\n// ======================\n\n/**\n * Base change request type.\n *\n * Note that e.g. type Base<typeof State.DRAFT> does not equal to Drafted\n * because Drafted includes additional information (namely, SubmitterInput).\n *\n * If the state of a CR matters, this type should not be used directly\n * and concrete types should be used instead.\n */\nexport interface Base<S extends StateType = StateType>\n{\n id: string;\n // decision: typeof Decision[keyof typeof Decision]\n // disposition?: typeof Disposition[keyof typeof Disposition]\n state: S;\n\n /**\n * Used to match against stakeholders declared in register metadata.\n */\n submittingStakeholderGitServerUsername: string;\n\n items: ProposalSet;\n\n /**\n * Against which register version changes were proposed.\n */\n registerVersion: string;\n\n /**\n * A link to external discussion.\n */\n externalDiscussionURI?: string;\n\n pastTransitions?: TransitionEntry[];\n}\n\n\nexport interface TransitionEntry {\n /** Verb in past tense. */\n label: string;\n\n timestamp: Date;\n fromState: StateType;\n toState: StateType;\n stakeholder: RegisterStakeholder;\n input: StateInput;\n}\n\n\nexport function isCreatedBy(stakeholder: RegisterStakeholder, cr: Base): boolean {\n return stakeholder.gitServerUsername?.trim() !== '' && stakeholder.gitServerUsername === cr.submittingStakeholderGitServerUsername;\n}\n\n/** Whether given `cr` can be edited (as in, items changed) by specified stakeholder. */\nexport function canBeEditedBy(stakeholder: RegisterStakeholder, cr: Base): boolean {\n return isCreatedBy(stakeholder, cr) && isEditableState(cr.state);\n}\n\n/**\n * Whether given `cr` can be deleted by given stakeholder.\n * Unlike editing, deletion is possible only if there are no items\n * and CR was never proposed.\n */\nexport function canBeDeletedBy(stakeholder: RegisterStakeholder, cr: Base): boolean {\n return (\n isCreatedBy(stakeholder, cr)\n && isDrafted(cr)\n //&& Object.keys(cr.items).length < 1 // Only allow deleting empty CRs\n && !hadBeenProposed(cr) // If it had been proposed, it should be withdrawn instead.\n );\n}\n\n\n/** Proposal structure for single-file proposal import format. */\nexport interface ImportableCR {\n /** Proposal data. */\n proposalDraft: Drafted,\n /** Register item data for additions & clarifications. */\n itemPayloads: ItemDataset,\n // TODO: Rename ImportableCR.itemPayloads to newItemData\n}\nexport function isImportableCR(val: any): val is ImportableCR {\n // TODO: More complete check\n return (\n val.proposalDraft.id\n && isDrafted(val.proposalDraft as Base)\n && Object.keys(val.itemPayloads).length > 0);\n}\n\n\n/**\n * A change request in any state.\n * Contains a superset of all possible properties, but all optional.\n * XXX: ^^^ This is a lie. Should be changed from | to & with Partial<>?\n */\nexport type SomeCR = \n | Drafted\n | Proposed\n | Withdrawn\n | ReturnedForClarificationByManager\n | SubmittedForControlBodyReview\n | ReturnedForClarificationByControlBody\n | Accepted\n | Rejected\n | RejectionUpheld\n | AcceptedOnAppeal\n | RejectedWithAppealWithdrawn;\n\nexport type Withdrawable =\n | Proposed\n | SubmittedForControlBodyReview\n | ReturnedForClarificationByManager\n | ReturnedForClarificationByControlBody;\n\nexport type Proposable =\n | Drafted\n | ReturnedForClarificationByManager\n | ReturnedForClarificationByControlBody;\n\nexport type SomeEditable =\n | Drafted\n | ReturnedForClarificationByManager\n | ReturnedForClarificationByControlBody;\n\nexport type Disposed =\n | Withdrawn\n | Accepted\n | Rejected\n | AcceptedOnAppeal\n | RejectionUpheld;\n\n\n// More specific change request types.\n// TODO: Refactor to avoid confusiong between current state e.g. Proposed)\n// and type (Proposed, to which all inheriting classes also conform)\n\nexport interface Drafted extends\n SubmitterInput,\n Base<typeof State.DRAFT> { timeStarted: Date, timeEdited: Date }\nexport function isDrafted(cr: Base): cr is Drafted {\n return isInState(cr, State.DRAFT);\n}\n\nexport interface Proposed extends\n Omit<Drafted, 'state'>,\n Base<typeof State.PROPOSED> { timeProposed: Date }\nexport function isProposed(cr: Base): cr is Proposed {\n return isInState(cr, State.PROPOSED);\n}\n\nexport interface Withdrawn extends\n Omit<Withdrawable, 'state'>,\n Base<typeof State.WITHDRAWN> { timeDisposed: Date }\nexport function isWithdrawn(cr: Base): cr is Withdrawn {\n return isInState(cr, State.WITHDRAWN);\n}\n\n/** CR was proposed at least once. */\nexport function hadBeenProposed(cr: Base): cr is Base & { timeProposed: Date } {\n return cr && cr.hasOwnProperty('timeProposed') && !!(cr as Proposed).timeProposed;\n}\nexport function hadBeenAccepted(cr: Base): cr is Accepted | AcceptedOnAppeal {\n return isDisposed(cr) && (isAccepted(cr) || isAcceptedOnAppeal(cr));\n}\n/** A proposal that had been disposed is not pending, not actionable. */\nexport function isDisposed(cr: Base): cr is Base & { timeDisposed: Date } {\n return cr && cr.hasOwnProperty('timeDisposed') && !!(cr as Disposed).timeDisposed;\n // TODO: include status checks, too?\n //return [\n // State.WITHDRAWN,\n // State.ACCEPTED,\n // State.REJECTED,\n // State.REJECTION_UPHELD_ON_APPEAL,\n // State.ACCEPTED_ON_APPEAL,\n //].some(s => cr.state === s);\n}\n\nexport interface SubmittedForControlBodyReview extends\n Omit<Proposed, 'state'>,\n RegisterManagerInput,\n Base<typeof State.SUBMITTED_FOR_CONTROL_BODY_REVIEW> {}\n\nexport function isSubmittedForControlBodyReview(cr: Base): cr is SubmittedForControlBodyReview {\n return isInState(cr, State.SUBMITTED_FOR_CONTROL_BODY_REVIEW)\n}\n\nexport interface ReturnedForClarificationByManager extends\n Omit<Proposed, 'state'>,\n RegisterManagerInput,\n Base<typeof State.RETURNED_FOR_CLARIFICATION> {}\n\nexport interface ReturnedForClarificationByControlBody extends\n Omit<SubmittedForControlBodyReview, 'state'>,\n ControlBodyInput,\n Base<typeof State.RETURNED_FOR_CLARIFICATION> {}\n\nexport function isReturnedForClarification(cr: Base): cr is (ReturnedForClarificationByManager | ReturnedForClarificationByControlBody) {\n return isInState(cr, State.RETURNED_FOR_CLARIFICATION)\n}\n\nexport interface Accepted extends\n Omit<SubmittedForControlBodyReview, 'state'>,\n ControlBodyInput,\n Base<typeof State.ACCEPTED> { timeDisposed: Date }\nexport function isAccepted(cr: Base): cr is Accepted {\n return isInState(cr, State.ACCEPTED);\n}\n\nexport interface Rejected extends\n Omit<SubmittedForControlBodyReview, 'state'>,\n ControlBodyInput,\n Base<typeof State.REJECTED> { timeDisposed: Date }\nexport function isRejected(cr: Base): cr is Rejected {\n return isInState(cr, State.REJECTED);\n}\n\nexport interface Appealed extends\n Omit<Rejected, 'state' | 'timeDisposed'>,\n AppealRequest,\n Base<typeof State.APPEALED> { timeDisposed: undefined }\nexport function isAppealed(cr: Base): cr is Appealed {\n return isInState(cr, State.APPEALED);\n}\n\nexport interface RejectionUpheld extends\n Omit<Appealed, 'state' | 'timeDisposed'>,\n RegisterOwnerInput,\n Base<typeof State.REJECTION_UPHELD_ON_APPEAL> { timeDisposed: Date }\nexport function isRejectedOnAppeal(cr: Base): cr is RejectionUpheld {\n return isInState(cr, State.REJECTION_UPHELD_ON_APPEAL);\n}\n\nexport interface AcceptedOnAppeal extends\n Omit<Appealed, 'state' | 'timeDisposed'>,\n RegisterOwnerInput,\n Base<typeof State.ACCEPTED_ON_APPEAL> { timeDisposed: Date }\nexport function isAcceptedOnAppeal(cr: Base): cr is AcceptedOnAppeal {\n return isInState(cr, State.ACCEPTED_ON_APPEAL);\n}\n\nexport interface RejectedWithAppealWithdrawn extends\n Omit<Appealed, 'state' | 'timeDisposed'>,\n Base<typeof State.APPEAL_WITHDRAWN> { timeDisposed: Date }\nexport function isRejectedWithAppealWithdrawn(cr: Base): cr is RejectedWithAppealWithdrawn {\n return isInState(cr, State.APPEAL_WITHDRAWN);\n}\n\n\n\n// Input required when transitioning to different states\n\nexport interface SubmitterInput {\n justification: string;\n}\nexport function hasSubmitterInput(val: any): val is SubmitterInput {\n return val.hasOwnProperty('justification') && typeof val.justification === 'string';\n}\nexport interface RegisterManagerInput {\n registerManagerNotes: string;\n}\nexport function hasRegisterManagerInput(val: any): val is RegisterManagerInput {\n return val.hasOwnProperty('registerManagerNotes') && typeof val.registerManagerNotes === 'string';\n}\nexport interface ControlBodyInput {\n controlBodyNotes: string;\n controlBodyDecisionEvent: string;\n}\nexport function hasControlBodyInput(val: any): val is ControlBodyInput {\n return (\n val.hasOwnProperty('controlBodyNotes') && typeof val.controlBodyNotes === 'string' &&\n val.hasOwnProperty('controlBodyDecisionEvent') && typeof val.controlBodyDecisionEvent === 'string');\n}\nexport interface AppealRequest {\n appealReason: string;\n}\nexport function hasAppealRequest(val: any): val is AppealRequest {\n return val.hasOwnProperty('appealReason') && typeof val.appealReason === 'string';\n}\nexport interface RegisterOwnerInput {\n registerOwnerNotes: string;\n}\nexport function hasRegisterOwnerInput(val: any): val is RegisterOwnerInput {\n return val.hasOwnProperty('registerOwnerNotes') && typeof val.registerOwnerNotes === 'string';\n}\n\nexport type StateInput =\n | SubmitterInput\n | RegisterManagerInput\n | ControlBodyInput\n | AppealRequest\n | RegisterOwnerInput;\n\n\n/** \n * CR type guard helper.\n * Normally you would not use it directly and instead use\n * more specific is[Type]() helper from this module.\n *\n * Checks CR type using the `state` property.\n * Does not validate other properties.\n *\n * Usage:\n *\n * @example\n * ```ts\n * let someCR;\n * if (isInState<Drafted>(someCR, State.DRAFT)) {\n * // Can assume someCR is Drafted\n * }\n * ```\n *\n * It’ll try to tell you if you mismatch those.\n *\n * @example\n * Will not compile:\n * ```ts\n * let someCR;\n * if (isInState<Drafted>(someCR, State.PROPOSED)) {\n * // Compile error\n * // because State.PROPOSED is not a possible value of Drafted[\"state\"]\n * }\n * ```\n *\n * @example\n * Incorrect usage (do not do this):\n * ```ts\n * let someCR;\n * if (isInState(someCR, State.DRAFT)) {\n * // Can NOT assume someCR is Drafted\n * // The compiler must know the expected concrete CR type\n * }\n * ```\n */\nfunction isInState<CR extends Base>(cr: Base, s: CR[\"state\"]): cr is CR {\n return cr.state === s;\n}\n\n\n\n\n// ===========\n// Transitions\n// ===========\n\n/**\n * A function that transitions CR1 to CR2.\n *\n * The function is declared to return the object\n * without the `state` field, it is set\n * by common wrapper function to reduce duplication.\n */\nexport type Transition<\n /** From CR of this subtype */\n CR1 extends Base,\n /** To CR of this subtype */\n CR2 extends Base,\n /** Using this extra information */\n P extends Record<string, any> | null = null,\n> = (cr: CR1, payload: P) => Omit<CR2, 'state'>;\n\n\nexport type AlterApprovedCR = (\n crID: string,\n proposals: ProposalSet,\n origItemData: ItemDataset,\n newItemData: ItemDataset,\n opts: Pick<DatasetContext, 'getMapReducedData'>,\n) => Promise<{\n proposals: ProposalSet,\n origItemData: ItemDataset,\n newItemData: ItemDataset,\n}>\n\n\n/**\n * Describes a transition.\n *\n * @typeParam CR1: Change request source state type\n * @typeParam CR2: Change request target state type\n * @typeParam P: Extra input needed to transition, if any\n */\nexport interface TransitionConfig<CR1 extends Base, CR2 extends Base, P extends Record<string, any> | null = null> {\n /**\n * Function that implements the transition.\n * Takes a CR in the original state and returns CR in the new state.\n * Additionally, takes appropriate payload, if any, for the transition\n * (e.g., register manager or control body notes).\n *\n * For function implementor:\n *\n * - Function MUST NOT modify CR in place.\n * - Function should throw if submitted payload does not conform to requirements.\n */\n func: Transition<CR1, CR2, P>;\n\n targetState: CR2[\"state\"];\n\n /** Title. Use verb. */\n title: string;\n\n hint?: string | JSX.Element;\n\n /** Widget that can be used to view or enter extra input. */\n Widget: P extends null ? null : React.FC<{ value: P, onChange?: (userInput: P) => void }>;\n\n /**\n * Function that returns true\n * if given stakeholder can perform this transition on given CR.\n */\n canBeTransitionedBy: (stakeholder: RegisterStakeholder, cr: CR1) => boolean;\n}\n\n\n// type TransitionSpec = {\n// [S1 in StateType]?: {\n// [S2 in StateType]?: Transition<Base<S1>, Base<S2>, Record<string, any>>\n// }\n// }\n\n\n/**\n * Source of truth for available transitions.\n * When updating change request business logic,\n * this is the type that should be modified.\n *\n * It will cause compile errors until transition implementation\n * is updated correspondingly.\n */\nexport type Transitions = {\n [State.DRAFT]: {\n // [State.DRAFT]:\n // TransitionConfig<Drafted, Drafted, SubmitterInput>;\n [State.WITHDRAWN]:\n TransitionConfig<Proposed, Withdrawn>;\n [State.PROPOSED]:\n TransitionConfig<Drafted, Proposed, SubmitterInput>;\n };\n [State.PROPOSED]: {\n [State.WITHDRAWN]:\n TransitionConfig<Proposed, Withdrawn>;\n [State.SUBMITTED_FOR_CONTROL_BODY_REVIEW]:\n TransitionConfig<Proposed, SubmittedForControlBodyReview, RegisterManagerInput>;\n [State.RETURNED_FOR_CLARIFICATION]:\n TransitionConfig<Proposed, ReturnedForClarificationByManager, RegisterManagerInput>;\n };\n [State.SUBMITTED_FOR_CONTROL_BODY_REVIEW]: {\n [State.WITHDRAWN]:\n TransitionConfig<SubmittedForControlBodyReview, Withdrawn>;\n [State.RETURNED_FOR_CLARIFICATION]:\n TransitionConfig<SubmittedForControlBodyReview, ReturnedForClarificationByControlBody, ControlBodyInput>;\n [State.REJECTED]:\n TransitionConfig<SubmittedForControlBodyReview, Rejected, ControlBodyInput>;\n [State.ACCEPTED]:\n TransitionConfig<SubmittedForControlBodyReview, Accepted, ControlBodyInput>;\n };\n [State.RETURNED_FOR_CLARIFICATION]: {\n [State.PROPOSED]:\n TransitionConfig<ReturnedForClarificationByManager | ReturnedForClarificationByControlBody, Proposed, SubmitterInput>;\n [State.WITHDRAWN]:\n TransitionConfig<ReturnedForClarificationByManager | ReturnedForClarificationByControlBody, Withdrawn>;\n };\n [State.REJECTED]: {\n [State.APPEALED]:\n TransitionConfig<Rejected, Appealed, AppealRequest>;\n };\n [State.APPEALED]: {\n [State.APPEAL_WITHDRAWN]:\n TransitionConfig<Appealed, RejectedWithAppealWithdrawn>;\n [State.ACCEPTED_ON_APPEAL]:\n TransitionConfig<Appealed, AcceptedOnAppeal, RegisterOwnerInput>;\n [State.REJECTION_UPHELD_ON_APPEAL]:\n TransitionConfig<Appealed, RejectionUpheld, RegisterOwnerInput>;\n };\n}\n\n\n// Utility\n// =======\n\nexport interface ProposalProps<P extends ChangeProposal> {\n proposal: P\n\n /** Highlight changes. */\n showDiff?: boolean\n\n /** In diff mode, only show changed data. (Provisional.) */\n showOnlyChanged?: boolean\n\n itemRef: InternalItemReference\n item: RegisterItem<Payload>\n itemBefore: P extends Clarification ? RegisterItem<Payload> : undefined\n onChange?: (newProposal: P) => void\n}\n"]}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = void 0;
|
|
7
|
+
|
|
8
|
+
var _react = _interopRequireWildcard(require("react"));
|
|
9
|
+
|
|
10
|
+
var _react2 = require("@emotion/react");
|
|
11
|
+
|
|
12
|
+
var _core = require("@blueprintjs/core");
|
|
13
|
+
|
|
14
|
+
var _Search = _interopRequireDefault(require("../sidebar/Search"));
|
|
15
|
+
|
|
16
|
+
var _util = require("../util");
|
|
17
|
+
|
|
18
|
+
var _models = require("../FilterCriteria/models");
|
|
19
|
+
|
|
20
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
21
|
+
|
|
22
|
+
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); }
|
|
23
|
+
|
|
24
|
+
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; }
|
|
25
|
+
|
|
26
|
+
/** @jsx jsx */
|
|
27
|
+
|
|
28
|
+
/** @jsxFrag React.Fragment */
|
|
29
|
+
const ItemSearch = (0, _react.memo)(function () {
|
|
30
|
+
return (0, _react2.jsx)(_util.TabContentsWithHeader, {
|
|
31
|
+
title: (0, _react2.jsx)(_react.default.Fragment, null, "Search all items")
|
|
32
|
+
}, (0, _react2.jsx)(_core.Card, {
|
|
33
|
+
css: (0, _react2.css)`flex: 1; box-shadow: none !important; position: absolute; border-radius: 0; display: flex; flex-flow: column nowrap; padding: 10px;`
|
|
34
|
+
}, (0, _react2.jsx)(_util.RegisterHelmet, null, (0, _react2.jsx)("title", null, "Search all items")), (0, _react2.jsx)(_Search.default, {
|
|
35
|
+
css: (0, _react2.css)`flex: 1;`,
|
|
36
|
+
//style={{ height: '100vh', width: '50vw', minWidth: '500px', maxWidth: '90vw' }}
|
|
37
|
+
implicitCriteria: _models.MATCHES_ANY_CRITERIA,
|
|
38
|
+
stateName: `all-items-search`
|
|
39
|
+
})));
|
|
40
|
+
});
|
|
41
|
+
var _default = {
|
|
42
|
+
main: ItemSearch,
|
|
43
|
+
title: "All items"
|
|
44
|
+
};
|
|
45
|
+
exports.default = _default;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AllItems.js","sourceRoot":"","sources":["../../../src/views/detail/AllItems.tsx"],"names":[],"mappings":"AAAA,eAAe;AACf,8BAA8B;AAE9B,OAAO,KAAK,EAAE,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC;AACpC,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EACL,IAAI,GACL,MAAM,mBAAmB,CAAC;AAC3B,OAAO,MAAM,MAAM,mBAAmB,CAAC;AACvC,OAAO,EAAE,cAAc,IAAI,MAAM,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAC;AAChD,OAAO,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAGhE,MAAM,UAAU,GAChB,IAAI,CAAC;IACH,OAAO,CACL,IAAC,qBAAqB,IAClB,KAAK,EAAE,6CAAqB;QAC9B,IAAC,IAAI,IAAC,GAAG,EAAE,GAAG,CAAA,qIAAqI;YACjJ,IAAC,MAAM;gBAAC,sCAA+B,CAAS;YAChD,IAAC,MAAM,IACL,GAAG,EAAE,GAAG,CAAA,UAAU;gBAClB,iFAAiF;gBACjF,gBAAgB,EAAE,oBAAoB,EACtC,SAAS,EAAE,kBAAkB,GAE7B,CACG,CACe,CACzB,CAAC;AACJ,CAAC,CAAC,CAAC;AAGH,eAAe;IACb,IAAI,EAAE,UAAU;IAChB,KAAK,EAAE,WAAW;CACV,CAAC","sourcesContent":["/** @jsx jsx */\n/** @jsxFrag React.Fragment */\n\nimport React, { memo } from 'react';\nimport { jsx, css } from '@emotion/react';\nimport {\n Card,\n} from '@blueprintjs/core';\nimport Search from '../sidebar/Search';\nimport { RegisterHelmet as Helmet } from '../util';\nimport { TabContentsWithHeader } from '../util';\nimport { MATCHES_ANY_CRITERIA } from '../FilterCriteria/models';\n\n\nconst ItemSearch: React.VoidFunctionComponent<Record<never, never>> =\nmemo(function () {\n return (\n <TabContentsWithHeader\n title={<>Search all items</>}>\n <Card css={css`flex: 1; box-shadow: none !important; position: absolute; border-radius: 0; display: flex; flex-flow: column nowrap; padding: 10px;`}>\n <Helmet><title>Search all items</title></Helmet>\n <Search\n css={css`flex: 1;`}\n //style={{ height: '100vh', width: '50vw', minWidth: '500px', maxWidth: '90vw' }}\n implicitCriteria={MATCHES_ANY_CRITERIA}\n stateName={`all-items-search`}\n //onOpenItem={onChooseItem ? handleOpenItem : undefined}\n />\n </Card>\n </TabContentsWithHeader>\n );\n});\n\n\nexport default {\n main: ItemSearch,\n title: \"All items\",\n} as const;\n"]}
|
|
@@ -61,6 +61,7 @@ const ProposalWork = (0, _react.memo)(function () {
|
|
|
61
61
|
getObjectData,
|
|
62
62
|
isBusy
|
|
63
63
|
} = (0, _react.useContext)(_context.DatasetContext);
|
|
64
|
+
const handleDeactivate = (0, _react.useCallback)(() => setActiveChangeRequestID === null || setActiveChangeRequestID === void 0 ? void 0 : setActiveChangeRequestID(null), [setActiveChangeRequestID]);
|
|
64
65
|
const handleDelete = (0, _react.useCallback)(async () => {
|
|
65
66
|
if (deleteCR && activeCR && setActiveChangeRequestID) {
|
|
66
67
|
await deleteCR();
|
|
@@ -194,7 +195,8 @@ const ProposalWork = (0, _react.memo)(function () {
|
|
|
194
195
|
proposal: activeCR,
|
|
195
196
|
register: register,
|
|
196
197
|
stakeholder: stakeholder,
|
|
197
|
-
onDelete: deleteCR ? handleDelete : undefined
|
|
198
|
+
onDelete: deleteCR ? handleDelete : undefined,
|
|
199
|
+
onDeactivate: setActiveChangeRequestID ? handleDeactivate : undefined
|
|
198
200
|
});
|
|
199
201
|
}
|
|
200
202
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ProposalWork.js","sourceRoot":"","sources":["../../../src/views/detail/ProposalWork.tsx"],"names":[],"mappings":"AAAA,eAAe;AACf,8BAA8B;AAE9B,OAAO,KAAK,EAAE,EAAE,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC;AACtE,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAElD,OAAO,EAAE,cAAc,EAAE,MAAM,0CAA0C,CAAC;AAG1E,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AACnE,OAAO,EAAE,oBAAoB,EAAE,MAAM,sCAAsC,CAAC;AAC5E,OAAO,WAAW,MAAM,6BAA6B,CAAC;AACtD,OAAO,eAAe,MAAM,iCAAiC,CAAC;AAC9D,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,yBAAyB,MAAM,6CAA6C,CAAC;AACpF,OAAO,EACL,oBAAoB,EACpB,mCAAmC,GACpC,MAAM,iBAAiB,CAAC;AAGzB,MAAM,YAAY,GAClB,IAAI,CAAC;IACH,MAAM,EAAE,aAAa,EAAE,QAAQ,EAAE,QAAQ,EAAE,GAAG,UAAU,CAAC,oBAAoB,CAAC,CAAC;IAC/E,MAAM,EACJ,gBAAgB,EAAE,QAAQ,EAC1B,WAAW,EACX,wBAAwB,EACxB,WAAW,GACZ,GAAG,UAAU,CAAC,UAAU,CAAC,CAAC;IAC3B,MAAM,EACJ,iBAAiB,EACjB,yBAAyB,EACzB,aAAa,EACb,gBAAgB,EAChB,aAAa,EACb,MAAM,GACP,GAAG,UAAU,CAAC,cAAc,CAAC,CAAC;IAE/B,MAAM,YAAY,GAAG,WAAW,CAAC,KAAK,IAAI,EAAE;QAC1C,IAAI,QAAQ,IAAI,QAAQ,IAAI,wBAAwB,EAAE;YACpD,MAAM,QAAQ,EAAE,CAAC;YACjB,wBAAwB,CAAC,IAAI,CAAC,CAAC;SAChC;IACH,CAAC,EAAE,CAAC,QAAQ,EAAE,wBAAwB,CAAC,CAAC,CAAC;IAEzC,IAAI,sBAAgF,CAAC;IACrF,IAAI;QACF,sBAAsB,GAAG,yBAAyB,EAAE,CAAC;KACtD;IAAC,OAAO,CAAC,EAAE;QACV,OAAO,CAAC,KAAK,CAAC,2CAA2C,CAAC,CAAC;QAC3D,sBAAsB,GAAG,SAAS,CAAC;KACpC;IACD,MAAM,sBAAsB,GAE5B,OAAO,CAAC,GAAG,EAAE;QACX,IAAI,WAAW,IAAI,WAAW,CAAC,WAAW,CAAC,IAAI,sBAAsB,KAAK,SAAS,EAAE;YACnF,OAAO,KAAK,UAAU,sBAAsB,CAAE,OAAe;;gBAC3D,MAAM,IAAI,GAAG,MAAM,CAAC,UAAU,EAAE,CAAC;gBACjC,OAAO,CAAC,oBAAoB,CAC1B,IAAI,EACJ,OAAO,EACP,MAAA,sBAAsB,aAAtB,sBAAsB,uBAAtB,sBAAsB,CAAE,EAAE,mCAAI,SAAS,EACvC,WAAY,CAAC,iBAAkB,CAChC,EAAE,IAAI,CAAC,CAAC;YACX,CAAC,CAAC;SACH;aAAM;YACL,OAAO,SAAS,CAAC;SAClB;IACH,CAAC,EAAE,CAAC,WAAW,EAAE,sBAAsB,aAAtB,sBAAsB,uBAAtB,sBAAsB,CAAE,EAAE,CAAC,CAAC,CAAC;IAE9C,MAAM,sBAAsB,GAE5B,OAAO,CAAC,GAAG,EAAE;QACX,IAAI,yBAAyB,IAAI,WAAW,IAAI,WAAW,CAAC,WAAW,CAAC,EAAE;YACxE,OAAO,KAAK,UAAU,sBAAsB;gBAC1C,MAAM,IAAI,GAAG,MAAM,yBAAyB,CAAC;oBAC3C,MAAM,EAAE,wCAAwC;oBAChD,OAAO,EAAE;wBACP,EAAE,IAAI,EAAE,YAAY,EAAE,UAAU,EAAE,CAAC,OAAO,CAAC,EAAE;qBAC9C;iBACF,CAAC,CAAC;gBACH,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAE,CAAC;gBACzC,IAAI,CAAC,QAAQ,EAAE;oBACb,MAAM,IAAI,KAAK,CAAC,sBAAsB,CAAC,CAAC;iBACzC;gBACD,IAAI,cAAc,CAAC,QAAQ,CAAC,EAAE;oBAC5B,IAAI;wBACF,MAAM,CAAC,SAAS,EAAE,IAAI,CAAC,GAAG,MAAM,mCAAmC,CACjE,QAAQ,EACR,WAAW,EACX,WAAY,CAAC,iBAAkB,EAC/B,aAAa,EACb,KAAK,UAAU,iBAAiB,CAAC,UAAU;4BACzC,MAAM,eAAe,GAAG,CAAC,GAAG,UAAU,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;gCACjE,CAAC,SAAS,CAAC,EAAE;oCACX,OAAO,EAAE;;uEAE0C,SAAS;;;qBAG3D;iCACF;6BACF,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;4BAEvD,MAAM,MAAM,GAEZ,MAAM,iBAAiB,CAAC;gCACtB,MAAM,EAAE,eAAe;6BACxB,CAAC,CAAC;4BAEH,OAAO,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,UAAU,EAAE,WAAW,CAAC,EAAE,EAAE;gCAC9D,MAAM,OAAO;gCACX,oDAAoD;gCACpD,mCAAmC;gCACnC,CAAC,KAAK,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;gCAClD,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE;oCACtB,MAAM,IAAI,KAAK,CAAC,8EAA8E,UAAU,EAAE,CAAC,CAAC;iCAC7G;qCAAM,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE;oCAC7B,MAAM,cAAc,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;oCAC5E,MAAM,IAAI,KAAK,CAAC,kFAAkF,UAAU,KAAK,cAAc,EAAE,CAAC,CAAC;iCACpI;qCAAM;oCACL,OAAO;wCACL,oDAAoD;wCACpD,CAAC,UAAU,CAAC,EAAE,iBAAiB,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC;qCAC9D,CAAC;iCACH;4BACH,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;wBACxD,CAAC,CACF,CAAC;wBACF,OAAO,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;qBAC1B;oBAAC,OAAO,CAAC,EAAE;wBACV,OAAO,CAAC,KAAK,CAAC,6BAA6B,EAAE,CAAC,CAAC,CAAC;wBAChD,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAC;qBAChD;iBACF;qBAAM;oBACL,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;iBAC5C;YACH,CAAC,CAAA;SACF;aAAM;YACL,OAAO,SAAS,CAAC;SAClB;IACH,CAAC,EAAE,CAAC,iBAAiB,EAAE,yBAAyB,EAAE,aAAa,EAAE,WAAW,CAAC,CAAC,CAAC;IAE/E,MAAM,CAAC,QAAQ,EAAE,QAAQ,CAAC,GAAG,OAAO,CAAC,GAAG,EAAE;QACxC,IAAI,aAAa,IAAI,wBAAwB,IAAI,CAAC,MAAM,EAAE;YACxD,OAAO;gBACL,sBAAsB;oBACpB,CAAC,CAAC,gBAAgB,CAAC,oBAAoB,EAAE,KAAK;wBAC1C,MAAM,CAAC,eAAe,EAAE,IAAI,CAAC,GAAG,MAAM,sBAAsB,EAAE,CAAC;wBAC/D,MAAM,aAAa,CAAC;4BAClB,aAAa,EAAE,iBAAiB;4BAChC,eAAe;yBAChB,CAAC,CAAC;wBACH,wBAAwB,CAAC,IAAI,CAAC,CAAC;oBACjC,CAAC,CAAC;oBACJ,CAAC,CAAC,SAAS;gBACb,sBAAsB;oBACpB,CAAC,CAAC,gBAAgB,CAAC,yBAAyB,EAAE,KAAK,WAAW,OAAe;wBACzE,MAAM,CAAC,eAAe,EAAE,IAAI,CAAC,GAAG,MAAM,sBAAsB,CAAC,OAAO,CAAC,CAAC;wBACtE,MAAM,aAAa,CAAC;4BAClB,aAAa,EAAE,4BAA4B,OAAO,EAAE;4BACpD,eAAe;yBAChB,CAAC,CAAC;wBACH,wBAAwB,CAAC,IAAI,CAAC,CAAC;oBACjC,CAAC,CAAC;oBACJ,CAAC,CAAC,SAAS;aACd,CAAC;SACH;aAAM;YACL,OAAO,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;SAC/B;IACH,CAAC,EAAE,CAAC,MAAM,EAAE,gBAAgB,EAAE,aAAa,EAAE,sBAAsB,EAAE,sBAAsB,CAAC,CAAC,CAAC;IAE9F,IAAI,CAAC,QAAQ,IAAI,CAAC,QAAQ,IAAI,CAAC,WAAW,EAAE;QAC1C,OAAO,IAAC,aAAa,IACnB,IAAI,EAAC,OAAO,EACZ,KAAK,EAAC,6BAA6B,EACnC,WAAW,EAAE;gBACX,+GAGI;gBACH,QAAQ,IAAI,WAAW,IAAI,WAAW,CAAC,WAAW,CAAC,IAAI,sBAAsB,KAAK,SAAS;oBAC1F,CAAC,CAAC;wBACE,gCAAW;wBACX,IAAC,eAAe,IACd,GAAG,EAAE,GAAG,CAAA,gBAAgB,EACxB,eAAe,EACb,CAAA,sBAAsB,aAAtB,sBAAsB,uBAAtB,sBAAsB,CAAE,YAAY;gCAClC,CAAC,CAAC,UAAU,CACR,sBAAsB,CAAC,YAAY,EACnC,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;gCACrC,CAAC,CAAC,IAAI,EACV,QAAQ,EAAE,QAAQ,EAClB,aAAa,EAAE,QAAQ,GACvB,CACD;oBACL,CAAC,CAAC,IAAI,CACP,GACH,CAAC;KACJ;SAAM;QACL,OAAO,IAAC,WAAW,IACjB,QAAQ,EAAE,QAAQ,EAClB,QAAQ,EAAE,QAAQ,EAClB,WAAW,EAAE,WAAW,EACxB,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,SAAS,GAC7C,CAAC;KACJ;AACH,CAAC,CAAC,CAAC;AAGH,MAAM,iBAAiB,GAAsD;IAC3E,MAAM,EAAE,aAAa,EAAE,QAAQ,EAAE,GAAG,UAAU,CAAC,oBAAoB,CAAC,CAAC;IACrE,OAAO,0BAAG,QAAQ;QAChB,CAAC,CAAC,sCAAgC;QAClC,CAAC,CAAC,+CAAuB,CAAI,CAAC;AAClC,CAAC,CAAC;AAGF,eAAe;IACb,IAAI,EAAE,YAAY;IAClB,KAAK,EAAE,iBAAiB;CAChB,CAAC","sourcesContent":["/** @jsx jsx */\n/** @jsxFrag React.Fragment */\n\nimport React, { useMemo, useContext, useCallback, memo } from 'react';\nimport { jsx, css } from '@emotion/react';\nimport { NonIdealState } from '@blueprintjs/core';\n\nimport { DatasetContext } from '@riboseinc/paneron-extension-kit/context';\nimport type { ObjectChangeset } from '@riboseinc/paneron-extension-kit/types/objects';\n\nimport { BrowserCtx } from '../BrowserCtx';\nimport { canImportCR, canCreateCR } from '../../types/stakeholder';\nimport { ChangeRequestContext } from '../../proposals/ChangeRequestContext';\nimport ProposalTab from '../../proposals/ProposalTab';\nimport NewProposalMenu from '../../proposals/NewProposalMenu';\nimport { isImportableCR } from '../../proposals/types';\nimport { itemPathToItemRef } from '../itemPathUtils';\nimport { formatDate } from '../util';\nimport useLatestAcceptedProposal from '../../views/hooks/useLatestAcceptedProposal';\nimport {\n newCRObjectChangeset,\n importedProposalToCRObjectChangeset,\n} from '../../proposals';\n\n\nconst ProposalWork: React.VoidFunctionComponent<Record<never, never>> =\nmemo(function () {\n const { changeRequest: activeCR, deleteCR } = useContext(ChangeRequestContext);\n const {\n registerMetadata: register,\n stakeholder,\n setActiveChangeRequestID,\n itemClasses,\n } = useContext(BrowserCtx);\n const {\n getMapReducedData,\n requestFileFromFilesystem,\n updateObjects,\n performOperation,\n getObjectData,\n isBusy,\n } = useContext(DatasetContext);\n\n const handleDelete = useCallback(async () => {\n if (deleteCR && activeCR && setActiveChangeRequestID) {\n await deleteCR();\n setActiveChangeRequestID(null);\n }\n }, [deleteCR, setActiveChangeRequestID]);\n\n let latestAcceptedProposal: ReturnType<typeof useLatestAcceptedProposal> | undefined;\n try {\n latestAcceptedProposal = useLatestAcceptedProposal();\n } catch (e) {\n console.error(\"Failed to obtain latest accepted proposal\");\n latestAcceptedProposal = undefined;\n }\n const getNewEmptyCRChangeset:\n undefined | ((idea: string) => Promise<[ObjectChangeset, string]>) =\n useMemo(() => {\n if (stakeholder && canCreateCR(stakeholder) && latestAcceptedProposal !== undefined) {\n return async function getNewEmptyCRChangeset (newIdea: string) {\n const crID = crypto.randomUUID();\n return [newCRObjectChangeset(\n crID,\n newIdea,\n latestAcceptedProposal?.id ?? 'initial',\n stakeholder!.gitServerUsername!,\n ), crID];\n };\n } else {\n return undefined;\n }\n }, [stakeholder, latestAcceptedProposal?.id]);\n\n const getImportedCRChangeset:\n undefined | (() => Promise<[ObjectChangeset, string]>) =\n useMemo(() => {\n if (requestFileFromFilesystem && stakeholder && canImportCR(stakeholder)) {\n return async function getImportedCRChangeset() {\n const data = await requestFileFromFilesystem({\n prompt: \"Select one register proposal JSON file\",\n filters: [\n { name: \"JSON files\", extensions: ['.json'] },\n ],\n });\n const fileData = Object.values(data)[0]!;\n if (!fileData) {\n throw new Error(\"No file was selected\");\n }\n if (isImportableCR(fileData)) {\n try {\n const [changeset, crID] = await importedProposalToCRObjectChangeset(\n fileData,\n itemClasses,\n stakeholder!.gitServerUsername!,\n getObjectData,\n async function resolvePredicates(predicates) {\n const mapReduceChains = [...predicates.values()].map(predicate => ({\n [predicate]: {\n mapFunc: `\n const data = value.data;\n if (!key.startsWith('/proposals/') && data && (${predicate})) {\n emit({ objectPath: key, objectData: value });\n }\n `,\n },\n })).reduce((prev, curr) => ({ ...prev, ...curr }), {});\n\n const result:\n Record<string, { objectPath: string, objectData: any }[] | {}> =\n await getMapReducedData({\n chains: mapReduceChains,\n });\n\n return Object.entries(result).map(([chainLabel, chainResult]) => {\n const objects =\n // Map returns an empty object if there’re no items,\n // but we promise to return a list.\n (Array.isArray(chainResult) ? chainResult : []);\n if (objects.length < 1) {\n throw new Error(`Unable to resolve predicate to item UUID: no item found matching predicate ${chainLabel}`);\n } else if (objects.length > 1) {\n const objectOverview = objects.map((o: any) => JSON.stringify(o)).join(', ')\n throw new Error(`Unable to resolve predicate to item UUID: more than one item matches predicate ${chainLabel}: ${objectOverview}`);\n } else {\n return {\n // There’s just one item anyway, hence `objects[0]`.\n [chainLabel]: itemPathToItemRef(false, objects[0].objectPath),\n };\n }\n }).reduce((prev, curr) => ({ ...prev, ...curr }), {});\n },\n );\n return [changeset, crID];\n } catch (e) {\n console.error(\"Error reading proposal data\", e);\n throw new Error(\"Error reading proposal data\");\n }\n } else {\n throw new Error(\"Invalid proposal format\");\n }\n }\n } else {\n return undefined;\n }\n }, [getMapReducedData, requestFileFromFilesystem, getObjectData, stakeholder]);\n\n const [importCR, createCR] = useMemo(() => {\n if (updateObjects && setActiveChangeRequestID && !isBusy) {\n return [\n getImportedCRChangeset\n ? performOperation('importing proposal', async function () {\n const [objectChangeset, crID] = await getImportedCRChangeset(); \n await updateObjects({\n commitMessage: 'import proposal',\n objectChangeset,\n });\n setActiveChangeRequestID(crID);\n })\n : undefined,\n getNewEmptyCRChangeset\n ? performOperation('creating blank proposal', async function (newIdea: string) {\n const [objectChangeset, crID] = await getNewEmptyCRChangeset(newIdea);\n await updateObjects({\n commitMessage: `start new empty proposal ${newIdea}`,\n objectChangeset,\n });\n setActiveChangeRequestID(crID);\n })\n : undefined,\n ];\n } else {\n return [undefined, undefined];\n }\n }, [isBusy, performOperation, updateObjects, getImportedCRChangeset, getNewEmptyCRChangeset]);\n\n if (!activeCR || !register || !stakeholder) {\n return <NonIdealState\n icon=\"clean\"\n title=\"Not working on any proposal\"\n description={<>\n <p>\n Choose an actionable proposal from the sidebar to the left\n and activate it by double-clicking\n </p>\n {register && stakeholder && canCreateCR(stakeholder) && latestAcceptedProposal !== undefined\n ? <>\n <p>—or—</p>\n <NewProposalMenu\n css={css`height: 200px;`}\n previousVersion={\n latestAcceptedProposal?.timeDisposed\n ? formatDate(\n latestAcceptedProposal.timeDisposed,\n { showTime: true, useUTC: true })\n : null}\n onImport={importCR}\n onCreateBlank={createCR}\n />\n </>\n : null}\n </>}\n />;\n } else {\n return <ProposalTab\n proposal={activeCR}\n register={register}\n stakeholder={stakeholder}\n onDelete={deleteCR ? handleDelete : undefined}\n />;\n }\n});\n\n\nconst ProposalWorkTitle: React.VoidFunctionComponent<Record<never, never>> = function () {\n const { changeRequest: activeCR } = useContext(ChangeRequestContext);\n return <>{activeCR\n ? <strong>Active proposal</strong>\n : <>Proposal dashboard</>}</>;\n};\n\n\nexport default {\n main: ProposalWork,\n title: ProposalWorkTitle,\n} as const;\n"]}
|
|
1
|
+
{"version":3,"file":"ProposalWork.js","sourceRoot":"","sources":["../../../src/views/detail/ProposalWork.tsx"],"names":[],"mappings":"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","sourcesContent":["/** @jsx jsx */\n/** @jsxFrag React.Fragment */\n\nimport React, { useMemo, useContext, useCallback, memo } from 'react';\nimport { jsx, css } from '@emotion/react';\nimport { NonIdealState } from '@blueprintjs/core';\n\nimport { DatasetContext } from '@riboseinc/paneron-extension-kit/context';\nimport type { ObjectChangeset } from '@riboseinc/paneron-extension-kit/types/objects';\n\nimport { BrowserCtx } from '../BrowserCtx';\nimport { canImportCR, canCreateCR } from '../../types/stakeholder';\nimport { ChangeRequestContext } from '../../proposals/ChangeRequestContext';\nimport ProposalTab from '../../proposals/ProposalTab';\nimport NewProposalMenu from '../../proposals/NewProposalMenu';\nimport { isImportableCR } from '../../proposals/types';\nimport { itemPathToItemRef } from '../itemPathUtils';\nimport { formatDate } from '../util';\nimport useLatestAcceptedProposal from '../../views/hooks/useLatestAcceptedProposal';\nimport {\n newCRObjectChangeset,\n importedProposalToCRObjectChangeset,\n} from '../../proposals';\n\n\nconst ProposalWork: React.VoidFunctionComponent<Record<never, never>> =\nmemo(function () {\n const { changeRequest: activeCR, deleteCR } = useContext(ChangeRequestContext);\n const {\n registerMetadata: register,\n stakeholder,\n setActiveChangeRequestID,\n itemClasses,\n } = useContext(BrowserCtx);\n const {\n getMapReducedData,\n requestFileFromFilesystem,\n updateObjects,\n performOperation,\n getObjectData,\n isBusy,\n } = useContext(DatasetContext);\n\n const handleDeactivate = useCallback(\n (() => setActiveChangeRequestID?.(null)),\n [setActiveChangeRequestID]);\n\n const handleDelete = useCallback(async () => {\n if (deleteCR && activeCR && setActiveChangeRequestID) {\n await deleteCR();\n setActiveChangeRequestID(null);\n }\n }, [deleteCR, setActiveChangeRequestID]);\n\n let latestAcceptedProposal: ReturnType<typeof useLatestAcceptedProposal> | undefined;\n try {\n latestAcceptedProposal = useLatestAcceptedProposal();\n } catch (e) {\n console.error(\"Failed to obtain latest accepted proposal\");\n latestAcceptedProposal = undefined;\n }\n const getNewEmptyCRChangeset:\n undefined | ((idea: string) => Promise<[ObjectChangeset, string]>) =\n useMemo(() => {\n if (stakeholder && canCreateCR(stakeholder) && latestAcceptedProposal !== undefined) {\n return async function getNewEmptyCRChangeset (newIdea: string) {\n const crID = crypto.randomUUID();\n return [newCRObjectChangeset(\n crID,\n newIdea,\n latestAcceptedProposal?.id ?? 'initial',\n stakeholder!.gitServerUsername!,\n ), crID];\n };\n } else {\n return undefined;\n }\n }, [stakeholder, latestAcceptedProposal?.id]);\n\n const getImportedCRChangeset:\n undefined | (() => Promise<[ObjectChangeset, string]>) =\n useMemo(() => {\n if (requestFileFromFilesystem && stakeholder && canImportCR(stakeholder)) {\n return async function getImportedCRChangeset() {\n const data = await requestFileFromFilesystem({\n prompt: \"Select one register proposal JSON file\",\n filters: [\n { name: \"JSON files\", extensions: ['.json'] },\n ],\n });\n const fileData = Object.values(data)[0]!;\n if (!fileData) {\n throw new Error(\"No file was selected\");\n }\n if (isImportableCR(fileData)) {\n try {\n const [changeset, crID] = await importedProposalToCRObjectChangeset(\n fileData,\n itemClasses,\n stakeholder!.gitServerUsername!,\n getObjectData,\n async function resolvePredicates(predicates) {\n const mapReduceChains = [...predicates.values()].map(predicate => ({\n [predicate]: {\n mapFunc: `\n const data = value.data;\n if (!key.startsWith('/proposals/') && data && (${predicate})) {\n emit({ objectPath: key, objectData: value });\n }\n `,\n },\n })).reduce((prev, curr) => ({ ...prev, ...curr }), {});\n\n const result:\n Record<string, { objectPath: string, objectData: any }[] | {}> =\n await getMapReducedData({\n chains: mapReduceChains,\n });\n\n return Object.entries(result).map(([chainLabel, chainResult]) => {\n const objects =\n // Map returns an empty object if there’re no items,\n // but we promise to return a list.\n (Array.isArray(chainResult) ? chainResult : []);\n if (objects.length < 1) {\n throw new Error(`Unable to resolve predicate to item UUID: no item found matching predicate ${chainLabel}`);\n } else if (objects.length > 1) {\n const objectOverview = objects.map((o: any) => JSON.stringify(o)).join(', ')\n throw new Error(`Unable to resolve predicate to item UUID: more than one item matches predicate ${chainLabel}: ${objectOverview}`);\n } else {\n return {\n // There’s just one item anyway, hence `objects[0]`.\n [chainLabel]: itemPathToItemRef(false, objects[0].objectPath),\n };\n }\n }).reduce((prev, curr) => ({ ...prev, ...curr }), {});\n },\n );\n return [changeset, crID];\n } catch (e) {\n console.error(\"Error reading proposal data\", e);\n throw new Error(\"Error reading proposal data\");\n }\n } else {\n throw new Error(\"Invalid proposal format\");\n }\n }\n } else {\n return undefined;\n }\n }, [getMapReducedData, requestFileFromFilesystem, getObjectData, stakeholder]);\n\n const [importCR, createCR] = useMemo(() => {\n if (updateObjects && setActiveChangeRequestID && !isBusy) {\n return [\n getImportedCRChangeset\n ? performOperation('importing proposal', async function () {\n const [objectChangeset, crID] = await getImportedCRChangeset(); \n await updateObjects({\n commitMessage: 'import proposal',\n objectChangeset,\n });\n setActiveChangeRequestID(crID);\n })\n : undefined,\n getNewEmptyCRChangeset\n ? performOperation('creating blank proposal', async function (newIdea: string) {\n const [objectChangeset, crID] = await getNewEmptyCRChangeset(newIdea);\n await updateObjects({\n commitMessage: `start new empty proposal ${newIdea}`,\n objectChangeset,\n });\n setActiveChangeRequestID(crID);\n })\n : undefined,\n ];\n } else {\n return [undefined, undefined];\n }\n }, [isBusy, performOperation, updateObjects, getImportedCRChangeset, getNewEmptyCRChangeset]);\n\n if (!activeCR || !register || !stakeholder) {\n return <NonIdealState\n icon=\"clean\"\n title=\"Not working on any proposal\"\n description={<>\n <p>\n Choose an actionable proposal from the sidebar to the left\n and activate it by double-clicking\n </p>\n {register && stakeholder && canCreateCR(stakeholder) && latestAcceptedProposal !== undefined\n ? <>\n <p>—or—</p>\n <NewProposalMenu\n css={css`height: 200px;`}\n previousVersion={\n latestAcceptedProposal?.timeDisposed\n ? formatDate(\n latestAcceptedProposal.timeDisposed,\n { showTime: true, useUTC: true })\n : null}\n onImport={importCR}\n onCreateBlank={createCR}\n />\n </>\n : null}\n </>}\n />;\n } else {\n return <ProposalTab\n proposal={activeCR}\n register={register}\n stakeholder={stakeholder}\n onDelete={(deleteCR) ? handleDelete : undefined}\n onDeactivate={setActiveChangeRequestID ? handleDeactivate : undefined}\n />;\n }\n});\n\n\nconst ProposalWorkTitle: React.VoidFunctionComponent<Record<never, never>> = function () {\n const { changeRequest: activeCR } = useContext(ChangeRequestContext);\n return <>{activeCR\n ? <strong>Active proposal</strong>\n : <>Proposal dashboard</>}</>;\n};\n\n\nexport default {\n main: ProposalWork,\n title: ProposalWorkTitle,\n} as const;\n"]}
|