3.4 KB97 lines
Blame
1/**
2 * Copyright (c) Meta Platforms, Inc. and affiliates.
3 *
4 * This source code is licensed under the MIT license found in the
5 * LICENSE file in the root directory of this source tree.
6 */
7
8import type {CommitInfo} from './types';
9
10import {Tooltip} from 'isl-components/Tooltip';
11import {atom, useAtomValue} from 'jotai';
12import {HighlightCommitsWhileHovering} from './HighlightedCommits';
13import {OperationDisabledButton} from './OperationDisabledButton';
14import {multiSubmitUpdateMessage} from './SubmitUpdateMessageInput';
15import {allDiffSummaries, codeReviewProvider} from './codeReview/CodeReviewInfo';
16import {submitAsDraft} from './codeReview/DraftCheckbox';
17import {publishWhenReady} from './codeReview/PublishWhenReadyCheckbox';
18import {t, T} from './i18n';
19import {readAtom, writeAtom} from './jotaiUtils';
20import {dagWithPreviews} from './previews';
21import {selectedCommits} from './selection';
22
23/**
24 * If the selected commits are submittable by the review provider,
25 * they may be submit.
26 */
27export const submittableSelection = atom(get => {
28 const selection = get(selectedCommits);
29 if (selection.size < 2) {
30 return undefined;
31 }
32 const provider = get(codeReviewProvider);
33 const diffSummaries = get(allDiffSummaries);
34
35 if (provider == null || diffSummaries == null) {
36 return undefined;
37 }
38
39 const dag = get(dagWithPreviews);
40 const commits = dag.getBatch(dag.sortAsc(dag.present(selection)));
41 const submittable =
42 (diffSummaries.value != null
43 ? provider?.getSubmittableDiffs(commits, diffSummaries.value)
44 : undefined) ?? [];
45
46 return submittable;
47});
48
49/**
50 * Button to submit the selected commits, if applicable.
51 * If `commit` is provided, only render the button if the commit is the bottom of the selected range.
52 * If `commit` is null, always show the button if there are commits to submit.
53 */
54export function SubmitSelectionButton({commit}: {commit?: CommitInfo}) {
55 const submittable = useAtomValue(submittableSelection);
56 const provider = useAtomValue(codeReviewProvider);
57
58 if (
59 provider == null ||
60 submittable == null ||
61 submittable.length < 2 ||
62 // show the button on the bottom commit of the submittable selection, if showing the button on a commit.
63 (commit != null && submittable?.[0]?.hash !== commit.hash)
64 ) {
65 return null;
66 }
67
68 return (
69 <Tooltip
70 title={t('Submit $count selected commits for code review with $provider', {
71 replace: {
72 $count: String(submittable.length),
73 $provider: provider.label ?? 'remote',
74 },
75 })}>
76 <HighlightCommitsWhileHovering toHighlight={submittable}>
77 <OperationDisabledButton
78 runOperation={() => {
79 const updateMessage = readAtom(multiSubmitUpdateMessage(submittable));
80 // clear update message on submit
81 writeAtom(multiSubmitUpdateMessage(submittable), '');
82 return provider.submitOperation(submittable, {
83 draft: readAtom(submitAsDraft),
84 updateMessage: updateMessage || undefined,
85 publishWhenReady: readAtom(publishWhenReady),
86 });
87 }}
88 contextKey={`submit-selection-${submittable[0].hash}`}>
89 <T replace={{$count: submittable.length, $action: provider.submitButtonLabel ?? 'Submit'}}>
90 $action $count commits
91 </T>
92 </OperationDisabledButton>
93 </HighlightCommitsWhileHovering>
94 </Tooltip>
95 );
96}
97