@activecollab/components 2.0.342 → 2.0.344
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/dist/cjs/components/Icons/collection/{SourceCode.js → GitRepository.js} +13 -11
- package/dist/cjs/components/Icons/collection/GitRepository.js.map +1 -0
- package/dist/cjs/components/Icons/collection/index.js +7 -7
- package/dist/cjs/components/Icons/collection/index.js.map +1 -1
- package/dist/cjs/presentation/shared/ConnectRepositoryDialog.js +272 -0
- package/dist/cjs/presentation/shared/ConnectRepositoryDialog.js.map +1 -0
- package/dist/cjs/presentation/shared/LinkBranchOrPullRequestDialog.js +690 -0
- package/dist/cjs/presentation/shared/LinkBranchOrPullRequestDialog.js.map +1 -0
- package/dist/cjs/presentation/shared/headers.js +259 -32
- package/dist/cjs/presentation/shared/headers.js.map +1 -1
- package/dist/cjs/presentation/shared/index.js +51 -0
- package/dist/cjs/presentation/shared/index.js.map +1 -1
- package/dist/esm/components/Icons/collection/GitRepository.d.ts +16 -0
- package/dist/esm/components/Icons/collection/GitRepository.d.ts.map +1 -0
- package/dist/esm/components/Icons/collection/{SourceCode.js → GitRepository.js} +13 -11
- package/dist/esm/components/Icons/collection/GitRepository.js.map +1 -0
- package/dist/esm/components/Icons/collection/index.d.ts +1 -1
- package/dist/esm/components/Icons/collection/index.d.ts.map +1 -1
- package/dist/esm/components/Icons/collection/index.js +1 -1
- package/dist/esm/components/Icons/collection/index.js.map +1 -1
- package/dist/esm/presentation/shared/ConnectRepositoryDialog.d.ts +51 -0
- package/dist/esm/presentation/shared/ConnectRepositoryDialog.d.ts.map +1 -0
- package/dist/esm/presentation/shared/ConnectRepositoryDialog.js +225 -0
- package/dist/esm/presentation/shared/ConnectRepositoryDialog.js.map +1 -0
- package/dist/esm/presentation/shared/LinkBranchOrPullRequestDialog.d.ts +7 -0
- package/dist/esm/presentation/shared/LinkBranchOrPullRequestDialog.d.ts.map +1 -0
- package/dist/esm/presentation/shared/LinkBranchOrPullRequestDialog.js +579 -0
- package/dist/esm/presentation/shared/LinkBranchOrPullRequestDialog.js.map +1 -0
- package/dist/esm/presentation/shared/headers.d.ts +8 -1
- package/dist/esm/presentation/shared/headers.d.ts.map +1 -1
- package/dist/esm/presentation/shared/headers.js +224 -30
- package/dist/esm/presentation/shared/headers.js.map +1 -1
- package/dist/esm/presentation/shared/index.d.ts +4 -0
- package/dist/esm/presentation/shared/index.d.ts.map +1 -1
- package/dist/esm/presentation/shared/index.js +2 -0
- package/dist/esm/presentation/shared/index.js.map +1 -1
- package/dist/index.js +229 -227
- package/dist/index.js.map +1 -1
- package/dist/index.min.js +1 -1
- package/dist/index.min.js.map +1 -1
- package/package.json +1 -1
- package/dist/cjs/components/Icons/collection/SourceCode.js.map +0 -1
- package/dist/esm/components/Icons/collection/SourceCode.d.ts +0 -16
- package/dist/esm/components/Icons/collection/SourceCode.d.ts.map +0 -1
- package/dist/esm/components/Icons/collection/SourceCode.js.map +0 -1
|
@@ -0,0 +1,579 @@
|
|
|
1
|
+
import React, { useCallback, useEffect, useRef, useState } from "react";
|
|
2
|
+
import styled, { createGlobalStyle } from "styled-components";
|
|
3
|
+
import { CONNECTABLE_REPOSITORIES, CONNECTIONS, ConnectRepositoryDialog, PROJECT_REPOSITORIES, RepositorySelect, serviceLabel } from "./ConnectRepositoryDialog";
|
|
4
|
+
import { Button } from "../../components/Button";
|
|
5
|
+
import { ChooseV2 } from "../../components/ChooseV2";
|
|
6
|
+
import { Dialog } from "../../components/Dialog";
|
|
7
|
+
import { Input } from "../../components/Input";
|
|
8
|
+
import { Label } from "../../components/Label";
|
|
9
|
+
import { SkeletonLoader } from "../../components/Loaders";
|
|
10
|
+
import { Select } from "../../components/Select";
|
|
11
|
+
import { SelectTrigger } from "../../components/SelectTrigger";
|
|
12
|
+
import { Caption1 } from "../../components/Typography";
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* "Link Branch or Pull Request" dialog — shared by every `Presentation/Task
|
|
16
|
+
* Source` story (the empty state and the populated Source Code section) so the
|
|
17
|
+
* flow lives in one place.
|
|
18
|
+
*
|
|
19
|
+
* Three modes (ChooseV2): **Link Existing** (default), **New Branch**, **New
|
|
20
|
+
* Pull Request**. The primary button is always enabled; validation runs on
|
|
21
|
+
* click and outlines the offending field. Esc does not close the dialog (it
|
|
22
|
+
* would lose entered data) — this is an action dialog.
|
|
23
|
+
*
|
|
24
|
+
* On open the body shows a ~1s skeleton, standing in for the future API loads
|
|
25
|
+
* that will drive the repository / branch / PR pickers.
|
|
26
|
+
*
|
|
27
|
+
* The **Link Existing** picker is a grouped, multi-level select: options are
|
|
28
|
+
* grouped by repository (with the connection name in parentheses), each option
|
|
29
|
+
* carries a branch or pull-request icon, everything is sorted by name and
|
|
30
|
+
* filterable via the search box at the top. The menu is sized to match the
|
|
31
|
+
* trigger width.
|
|
32
|
+
*/
|
|
33
|
+
|
|
34
|
+
const SANS = '-apple-system, BlinkMacSystemFont, "Roboto", "Helvetica Neue", Arial, sans-serif';
|
|
35
|
+
|
|
36
|
+
/* ---- Mock data ------------------------------------------------------- */
|
|
37
|
+
|
|
38
|
+
const LINKABLES = [{
|
|
39
|
+
id: "pr-500",
|
|
40
|
+
kind: "pr",
|
|
41
|
+
// Deliberately long, to show the name truncating with an ellipsis while the
|
|
42
|
+
// right-aligned detail and radio stay visible.
|
|
43
|
+
name: "#500 Refactor rank recalculation to support multi-region contract archival and backfill",
|
|
44
|
+
repoId: "backend",
|
|
45
|
+
updatedMinutesAgo: 8,
|
|
46
|
+
author: "Nikola M."
|
|
47
|
+
}, {
|
|
48
|
+
id: "branch-cache",
|
|
49
|
+
kind: "branch",
|
|
50
|
+
name: "spike/rank-cache",
|
|
51
|
+
repoId: "backend",
|
|
52
|
+
updatedMinutesAgo: 30
|
|
53
|
+
}, {
|
|
54
|
+
id: "branch-export",
|
|
55
|
+
kind: "branch",
|
|
56
|
+
name: "feature/retainer-export-34",
|
|
57
|
+
repoId: "backend",
|
|
58
|
+
updatedMinutesAgo: 5 * 60
|
|
59
|
+
}, {
|
|
60
|
+
id: "pr-119900",
|
|
61
|
+
kind: "pr",
|
|
62
|
+
name: "#119900 Rank API endpoints",
|
|
63
|
+
repoId: "backend",
|
|
64
|
+
updatedMinutesAgo: 2 * 24 * 60,
|
|
65
|
+
author: "Ilija S."
|
|
66
|
+
}, {
|
|
67
|
+
id: "branch-fe-retainers",
|
|
68
|
+
kind: "branch",
|
|
69
|
+
name: "feature/retainers-ui-34",
|
|
70
|
+
repoId: "frontend",
|
|
71
|
+
updatedMinutesAgo: 2 * 60
|
|
72
|
+
}, {
|
|
73
|
+
id: "pr-412",
|
|
74
|
+
kind: "pr",
|
|
75
|
+
name: "#412 Contract list filters",
|
|
76
|
+
repoId: "frontend",
|
|
77
|
+
updatedMinutesAgo: 24 * 60,
|
|
78
|
+
author: "Marko K."
|
|
79
|
+
}, {
|
|
80
|
+
id: "mr-88",
|
|
81
|
+
kind: "pr",
|
|
82
|
+
name: "!88 Bump worker memory",
|
|
83
|
+
repoId: "infra",
|
|
84
|
+
updatedMinutesAgo: 3 * 24 * 60,
|
|
85
|
+
author: "Ana P."
|
|
86
|
+
}, {
|
|
87
|
+
id: "branch-deploy",
|
|
88
|
+
kind: "branch",
|
|
89
|
+
name: "chore/deploy-rank-cache",
|
|
90
|
+
repoId: "infra",
|
|
91
|
+
updatedMinutesAgo: 24 * 60
|
|
92
|
+
}];
|
|
93
|
+
const MONTHS = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
|
|
94
|
+
const pad = n => String(n).padStart(2, "0");
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Reproduces the format of ActiveCollab's standard `Ago` component
|
|
98
|
+
* (`Angie.functions.ago()`) for the mock: "Just now", "N minutes ago",
|
|
99
|
+
* "Today HH:mm", "Yesterday HH:mm", "MMM D. HH:mm", else "MMM D. YYYY HH:mm".
|
|
100
|
+
* Production must use the real component.
|
|
101
|
+
*/
|
|
102
|
+
const formatAgo = minutesAgo => {
|
|
103
|
+
const now = new Date();
|
|
104
|
+
const then = new Date(now.getTime() - minutesAgo * 60000);
|
|
105
|
+
if (minutesAgo < 2) {
|
|
106
|
+
return "Just now";
|
|
107
|
+
}
|
|
108
|
+
if (minutesAgo < 60) {
|
|
109
|
+
return Math.floor(minutesAgo) + " minutes ago";
|
|
110
|
+
}
|
|
111
|
+
const time = pad(then.getHours()) + ":" + pad(then.getMinutes());
|
|
112
|
+
if (then.toDateString() === now.toDateString()) {
|
|
113
|
+
return "Today " + time;
|
|
114
|
+
}
|
|
115
|
+
const yesterday = new Date(now.getTime() - 24 * 60 * 60000);
|
|
116
|
+
if (then.toDateString() === yesterday.toDateString()) {
|
|
117
|
+
return "Yesterday " + time;
|
|
118
|
+
}
|
|
119
|
+
const monthDay = MONTHS[then.getMonth()] + " " + then.getDate() + ".";
|
|
120
|
+
if (then.getFullYear() === now.getFullYear()) {
|
|
121
|
+
return monthDay + " " + time;
|
|
122
|
+
}
|
|
123
|
+
return monthDay + " " + then.getFullYear() + " " + time;
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* The detail shown on the right of an option: a branch keeps just the time of
|
|
128
|
+
* its last activity; a pull request appends the author ("… by Name").
|
|
129
|
+
*/
|
|
130
|
+
const linkableDetail = item => item.kind === "pr" && item.author ? formatAgo(item.updatedMinutesAgo) + " by " + item.author : formatAgo(item.updatedMinutesAgo);
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Grouped options for the Select. One group per repository, labelled
|
|
134
|
+
* "repo (Org, Type)" and sorted by name; inside a group, branches and PRs are
|
|
135
|
+
* ordered by latest activity (freshest first). Standard option rendering shows
|
|
136
|
+
* the name (truncated) with the detail right-aligned and a radio.
|
|
137
|
+
*/
|
|
138
|
+
const GROUPED_OPTIONS = PROJECT_REPOSITORIES.map(repo => {
|
|
139
|
+
const connection = CONNECTIONS.find(c => c.id === repo.connectionId);
|
|
140
|
+
const items = LINKABLES.filter(l => l.repoId === repo.id).sort((a, b) => a.updatedMinutesAgo - b.updatedMinutesAgo).map(l => ({
|
|
141
|
+
id: l.id,
|
|
142
|
+
name: l.name,
|
|
143
|
+
additionalInfo: linkableDetail(l)
|
|
144
|
+
}));
|
|
145
|
+
return {
|
|
146
|
+
id: repo.id,
|
|
147
|
+
name: connection ? repo.name + " (" + connection.name + ", " + serviceLabel(connection.service) + ")" : repo.name,
|
|
148
|
+
options: items
|
|
149
|
+
};
|
|
150
|
+
}).filter(group => group.options.length > 0).sort((a, b) => a.name.localeCompare(b.name));
|
|
151
|
+
const ALL_ITEMS = LINKABLES;
|
|
152
|
+
|
|
153
|
+
/* ---- Branch mock data (for the New Branch / New Pull Request bases) --- */
|
|
154
|
+
|
|
155
|
+
const BRANCHES = [
|
|
156
|
+
// activecollab/backend
|
|
157
|
+
{
|
|
158
|
+
id: "backend-main",
|
|
159
|
+
name: "main",
|
|
160
|
+
repoId: "backend",
|
|
161
|
+
isDefault: true,
|
|
162
|
+
updatedMinutesAgo: 60
|
|
163
|
+
}, {
|
|
164
|
+
id: "backend-cache",
|
|
165
|
+
name: "spike/rank-cache",
|
|
166
|
+
repoId: "backend",
|
|
167
|
+
updatedMinutesAgo: 30
|
|
168
|
+
}, {
|
|
169
|
+
id: "backend-export",
|
|
170
|
+
name: "feature/retainer-export-34",
|
|
171
|
+
repoId: "backend",
|
|
172
|
+
updatedMinutesAgo: 5 * 60
|
|
173
|
+
}, {
|
|
174
|
+
id: "backend-hotfix",
|
|
175
|
+
name: "hotfix/rank-typo",
|
|
176
|
+
repoId: "backend",
|
|
177
|
+
updatedMinutesAgo: 3 * 24 * 60
|
|
178
|
+
},
|
|
179
|
+
// activecollab/frontend
|
|
180
|
+
{
|
|
181
|
+
id: "frontend-main",
|
|
182
|
+
name: "main",
|
|
183
|
+
repoId: "frontend",
|
|
184
|
+
isDefault: true,
|
|
185
|
+
updatedMinutesAgo: 90
|
|
186
|
+
}, {
|
|
187
|
+
id: "frontend-retainers",
|
|
188
|
+
name: "feature/retainers-ui-34",
|
|
189
|
+
repoId: "frontend",
|
|
190
|
+
updatedMinutesAgo: 2 * 60
|
|
191
|
+
}, {
|
|
192
|
+
id: "frontend-filters",
|
|
193
|
+
name: "feature/contract-filters",
|
|
194
|
+
repoId: "frontend",
|
|
195
|
+
updatedMinutesAgo: 24 * 60
|
|
196
|
+
},
|
|
197
|
+
// activecollab/infrastructure
|
|
198
|
+
{
|
|
199
|
+
id: "infra-master",
|
|
200
|
+
name: "master",
|
|
201
|
+
repoId: "infra",
|
|
202
|
+
isDefault: true,
|
|
203
|
+
updatedMinutesAgo: 6 * 60
|
|
204
|
+
}, {
|
|
205
|
+
id: "infra-deploy",
|
|
206
|
+
name: "chore/deploy-rank-cache",
|
|
207
|
+
repoId: "infra",
|
|
208
|
+
updatedMinutesAgo: 24 * 60
|
|
209
|
+
}];
|
|
210
|
+
const repoBranches = repoId => BRANCHES.filter(b => b.repoId === repoId);
|
|
211
|
+
const repoDefaultBranchId = repoId => {
|
|
212
|
+
var _repoBranches$find$id, _repoBranches$find;
|
|
213
|
+
return (_repoBranches$find$id = (_repoBranches$find = repoBranches(repoId).find(b => b.isDefault)) == null ? void 0 : _repoBranches$find.id) != null ? _repoBranches$find$id : null;
|
|
214
|
+
};
|
|
215
|
+
/**
|
|
216
|
+
* Base-branch options (Create From / Merge Into): the default branch first with
|
|
217
|
+
* no timestamp, then the rest sorted by latest activity (freshest first), each
|
|
218
|
+
* with a muted "last activity" time.
|
|
219
|
+
*/
|
|
220
|
+
const baseBranchOptions = repoId => {
|
|
221
|
+
const branches = repoBranches(repoId);
|
|
222
|
+
const defaults = branches.filter(b => b.isDefault).map(b => ({
|
|
223
|
+
id: b.id,
|
|
224
|
+
name: b.name
|
|
225
|
+
}));
|
|
226
|
+
const rest = branches.filter(b => !b.isDefault).sort((a, b) => a.updatedMinutesAgo - b.updatedMinutesAgo).map(b => ({
|
|
227
|
+
id: b.id,
|
|
228
|
+
name: b.name,
|
|
229
|
+
additionalInfo: formatAgo(b.updatedMinutesAgo)
|
|
230
|
+
}));
|
|
231
|
+
return [...defaults, ...rest];
|
|
232
|
+
};
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* Source-branch options (New Pull Request): the default branch is excluded — you
|
|
236
|
+
* don't open a PR to merge the trunk into a feature branch — and the rest are
|
|
237
|
+
* sorted by latest activity, each with a muted "last activity" time.
|
|
238
|
+
*/
|
|
239
|
+
const sourceBranchOptions = repoId => repoBranches(repoId).filter(b => !b.isDefault).sort((a, b) => a.updatedMinutesAgo - b.updatedMinutesAgo).map(b => ({
|
|
240
|
+
id: b.id,
|
|
241
|
+
name: b.name,
|
|
242
|
+
additionalInfo: formatAgo(b.updatedMinutesAgo)
|
|
243
|
+
}));
|
|
244
|
+
|
|
245
|
+
/* ---- Styles ---------------------------------------------------------- */
|
|
246
|
+
|
|
247
|
+
const StyledLinkBody = styled.div.withConfig({
|
|
248
|
+
displayName: "LinkBranchOrPullRequestDialog__StyledLinkBody",
|
|
249
|
+
componentId: "sc-2wiwoe-0"
|
|
250
|
+
})(["font-family:", ";.lk-tabbody{margin-top:18px;}.lk-field{margin-bottom:16px;}.lk-field:last-child{margin-bottom:0;}.lk-label{display:block;margin-bottom:6px;}.lk-control,.lk-control.c-input-wrapper{width:100%;max-width:none;}.lk-repo-hint{display:block;margin-top:8px;}.lk-repo-link{background:none;border:none;padding:0;font:inherit;color:var(--color-primary);cursor:pointer;}.lk-repo-link:hover{text-decoration:underline;}.lk-skeleton .sk-row{margin-bottom:18px;}.lk-skeleton .sk-choose{width:100%;height:36px;border-radius:6px;}.lk-skeleton .sk-label{width:160px;height:12px;margin-bottom:8px;}.lk-skeleton .sk-control{width:100%;height:40px;border-radius:6px;}"], SANS);
|
|
251
|
+
|
|
252
|
+
/**
|
|
253
|
+
* The grouped select menu renders through a portal, so the "match the trigger
|
|
254
|
+
* width" override has to be global, scoped to the menu's class. `$menuWidth` is
|
|
255
|
+
* measured from the trigger and injected here.
|
|
256
|
+
*/
|
|
257
|
+
const MenuGlobalStyle = createGlobalStyle([".c-select.lk-existing-select-menu{", "}.c-select.lk-existing-select-menu .c-option--text + span{color:var(--color-theme-600);font-size:12px;}"], _ref => {
|
|
258
|
+
let $menuWidth = _ref.$menuWidth;
|
|
259
|
+
return $menuWidth ? "width: " + $menuWidth + "px !important; max-width: none !important;" : "";
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
/**
|
|
263
|
+
* Per-instance global style for a branch select menu: matches the trigger width
|
|
264
|
+
* and applies the standard muted styling to the right-aligned "last activity".
|
|
265
|
+
*/
|
|
266
|
+
const BranchMenuGlobalStyle = createGlobalStyle([".c-select.", "{", "}.c-select.", " .c-option--text + span{color:var(--color-theme-600);font-size:12px;}"], p => p.$cls, p => p.$w ? "width: " + p.$w + "px !important; max-width: none !important;" : "", p => p.$cls);
|
|
267
|
+
const BranchSelectWrap = styled.div.withConfig({
|
|
268
|
+
displayName: "LinkBranchOrPullRequestDialog__BranchSelectWrap",
|
|
269
|
+
componentId: "sc-2wiwoe-1"
|
|
270
|
+
})(["font-family:", ";.branch-trigger{width:100%;max-width:none;}"], SANS);
|
|
271
|
+
/**
|
|
272
|
+
* Flat branch picker (Create From / Source Branch / Merge Into). The caller
|
|
273
|
+
* supplies the option order (default-first or activity-sorted); the DS internal
|
|
274
|
+
* alphabetical sort is disabled so that order is preserved.
|
|
275
|
+
*/
|
|
276
|
+
const BranchSelect = _ref2 => {
|
|
277
|
+
var _options$find$name, _options$find;
|
|
278
|
+
let options = _ref2.options,
|
|
279
|
+
selected = _ref2.selected,
|
|
280
|
+
onChange = _ref2.onChange,
|
|
281
|
+
_ref2$placeholder = _ref2.placeholder,
|
|
282
|
+
placeholder = _ref2$placeholder === void 0 ? "Select branch" : _ref2$placeholder;
|
|
283
|
+
const wrapRef = useRef(null);
|
|
284
|
+
const _useState = useState(),
|
|
285
|
+
menuWidth = _useState[0],
|
|
286
|
+
setMenuWidth = _useState[1];
|
|
287
|
+
const _useState2 = useState(() => "branch-select-menu-" + Math.random().toString(36).slice(2)),
|
|
288
|
+
menuCls = _useState2[0];
|
|
289
|
+
const measure = useCallback(() => {
|
|
290
|
+
if (wrapRef.current) {
|
|
291
|
+
setMenuWidth(wrapRef.current.offsetWidth);
|
|
292
|
+
}
|
|
293
|
+
}, []);
|
|
294
|
+
useEffect(() => {
|
|
295
|
+
measure();
|
|
296
|
+
}, [measure]);
|
|
297
|
+
const selectedName = (_options$find$name = (_options$find = options.find(o => o.id === selected)) == null ? void 0 : _options$find.name) != null ? _options$find$name : placeholder;
|
|
298
|
+
return /*#__PURE__*/React.createElement(BranchSelectWrap, {
|
|
299
|
+
ref: wrapRef
|
|
300
|
+
}, /*#__PURE__*/React.createElement(BranchMenuGlobalStyle, {
|
|
301
|
+
$cls: menuCls,
|
|
302
|
+
$w: menuWidth
|
|
303
|
+
}), /*#__PURE__*/React.createElement(Select, {
|
|
304
|
+
options: options,
|
|
305
|
+
selected: selected === null ? undefined : selected,
|
|
306
|
+
onChange: v => onChange(String(v)),
|
|
307
|
+
placeholder: "Search branches",
|
|
308
|
+
selectClassName: menuCls,
|
|
309
|
+
onSelectOpen: measure,
|
|
310
|
+
disabledInternalSort: true,
|
|
311
|
+
forceCloseMenu: true,
|
|
312
|
+
target: /*#__PURE__*/React.createElement(SelectTrigger, {
|
|
313
|
+
className: "branch-trigger",
|
|
314
|
+
typographyProps: selected === null ? {
|
|
315
|
+
color: "tertiary"
|
|
316
|
+
} : undefined
|
|
317
|
+
}, selectedName)
|
|
318
|
+
}));
|
|
319
|
+
};
|
|
320
|
+
const MODE_OPTIONS = [{
|
|
321
|
+
id: "existing",
|
|
322
|
+
name: "Link Existing"
|
|
323
|
+
}, {
|
|
324
|
+
id: "branch",
|
|
325
|
+
name: "New Branch"
|
|
326
|
+
}, {
|
|
327
|
+
id: "pr",
|
|
328
|
+
name: "New Pull Request"
|
|
329
|
+
}];
|
|
330
|
+
export const LinkBranchOrPullRequestDialog = _ref3 => {
|
|
331
|
+
var _ALL_ITEMS$find$name, _ALL_ITEMS$find;
|
|
332
|
+
let open = _ref3.open,
|
|
333
|
+
onClose = _ref3.onClose;
|
|
334
|
+
const _useState3 = useState("existing"),
|
|
335
|
+
mode = _useState3[0],
|
|
336
|
+
setMode = _useState3[1];
|
|
337
|
+
const _useState4 = useState(null),
|
|
338
|
+
selected = _useState4[0],
|
|
339
|
+
setSelected = _useState4[1];
|
|
340
|
+
const _useState5 = useState("feature/retainers-34"),
|
|
341
|
+
branchName = _useState5[0],
|
|
342
|
+
setBranchName = _useState5[1];
|
|
343
|
+
const _useState6 = useState("#34 Retainers & Contracts functionality"),
|
|
344
|
+
prTitle = _useState6[0],
|
|
345
|
+
setPrTitle = _useState6[1];
|
|
346
|
+
const _useState7 = useState(false),
|
|
347
|
+
attempted = _useState7[0],
|
|
348
|
+
setAttempted = _useState7[1];
|
|
349
|
+
const _useState8 = useState(true),
|
|
350
|
+
loading = _useState8[0],
|
|
351
|
+
setLoading = _useState8[1];
|
|
352
|
+
const _useState9 = useState(),
|
|
353
|
+
menuWidth = _useState9[0],
|
|
354
|
+
setMenuWidth = _useState9[1];
|
|
355
|
+
|
|
356
|
+
// Repository picker (New Branch / New Pull Request) + connect-repository flow.
|
|
357
|
+
const _useState0 = useState("backend"),
|
|
358
|
+
repo = _useState0[0],
|
|
359
|
+
setRepo = _useState0[1];
|
|
360
|
+
const _useState1 = useState(false),
|
|
361
|
+
connectOpen = _useState1[0],
|
|
362
|
+
setConnectOpen = _useState1[1];
|
|
363
|
+
const _useState10 = useState([]),
|
|
364
|
+
extraRepos = _useState10[0],
|
|
365
|
+
setExtraRepos = _useState10[1];
|
|
366
|
+
|
|
367
|
+
// Branch bases. Create From / Merge Into default to the repo's default branch;
|
|
368
|
+
// Source Branch starts unselected.
|
|
369
|
+
const _useState11 = useState(() => repoDefaultBranchId("backend")),
|
|
370
|
+
createFrom = _useState11[0],
|
|
371
|
+
setCreateFrom = _useState11[1];
|
|
372
|
+
const _useState12 = useState(null),
|
|
373
|
+
sourceBranch = _useState12[0],
|
|
374
|
+
setSourceBranch = _useState12[1];
|
|
375
|
+
const _useState13 = useState(() => repoDefaultBranchId("backend")),
|
|
376
|
+
mergeInto = _useState13[0],
|
|
377
|
+
setMergeInto = _useState13[1];
|
|
378
|
+
|
|
379
|
+
// When the repository changes, reset the bases: default branch for
|
|
380
|
+
// Create From / Merge Into, nothing for Source Branch.
|
|
381
|
+
useEffect(() => {
|
|
382
|
+
const defaultId = repoDefaultBranchId(repo);
|
|
383
|
+
setCreateFrom(defaultId);
|
|
384
|
+
setMergeInto(defaultId);
|
|
385
|
+
setSourceBranch(null);
|
|
386
|
+
}, [repo]);
|
|
387
|
+
const fieldRef = useRef(null);
|
|
388
|
+
|
|
389
|
+
// Simulate the API loads that will drive the pickers: a ~1s skeleton on open.
|
|
390
|
+
useEffect(() => {
|
|
391
|
+
if (!open) {
|
|
392
|
+
return undefined;
|
|
393
|
+
}
|
|
394
|
+
setLoading(true);
|
|
395
|
+
const timer = window.setTimeout(() => setLoading(false), 1000);
|
|
396
|
+
return () => window.clearTimeout(timer);
|
|
397
|
+
}, [open]);
|
|
398
|
+
const measureMenu = useCallback(() => {
|
|
399
|
+
if (fieldRef.current) {
|
|
400
|
+
setMenuWidth(fieldRef.current.offsetWidth);
|
|
401
|
+
}
|
|
402
|
+
}, []);
|
|
403
|
+
|
|
404
|
+
// Keep the menu width in sync with the trigger once the form is visible.
|
|
405
|
+
useEffect(() => {
|
|
406
|
+
if (open && !loading && mode === "existing") {
|
|
407
|
+
measureMenu();
|
|
408
|
+
}
|
|
409
|
+
}, [open, loading, mode, measureMenu]);
|
|
410
|
+
|
|
411
|
+
// Submit is always enabled; validation runs on click and outlines fields.
|
|
412
|
+
const existingInvalid = attempted && mode === "existing" && selected === null;
|
|
413
|
+
const branchInvalid = attempted && mode === "branch" && branchName.trim() === "";
|
|
414
|
+
const titleInvalid = attempted && mode === "pr" && prTitle.trim() === "";
|
|
415
|
+
const primaryLabel = mode === "existing" ? "Link" : mode === "branch" ? "Create Branch" : "Create Pull Request";
|
|
416
|
+
const close = () => {
|
|
417
|
+
setAttempted(false);
|
|
418
|
+
onClose();
|
|
419
|
+
};
|
|
420
|
+
const handleSubmit = () => {
|
|
421
|
+
const valid = mode === "existing" ? selected !== null : mode === "branch" ? branchName.trim() !== "" : prTitle.trim() !== "";
|
|
422
|
+
if (!valid) {
|
|
423
|
+
setAttempted(true);
|
|
424
|
+
return;
|
|
425
|
+
}
|
|
426
|
+
close();
|
|
427
|
+
};
|
|
428
|
+
const changeMode = next => {
|
|
429
|
+
setMode(next);
|
|
430
|
+
setAttempted(false);
|
|
431
|
+
};
|
|
432
|
+
const selectedLabel = (_ALL_ITEMS$find$name = (_ALL_ITEMS$find = ALL_ITEMS.find(o => o.id === selected)) == null ? void 0 : _ALL_ITEMS$find.name) != null ? _ALL_ITEMS$find$name : "Select branch or pull request";
|
|
433
|
+
|
|
434
|
+
// Repositories already on the project (plus any just connected), and the
|
|
435
|
+
// remaining ones that can still be connected from here.
|
|
436
|
+
const projectRepos = [...PROJECT_REPOSITORIES, ...extraRepos];
|
|
437
|
+
const connectableRepos = CONNECTABLE_REPOSITORIES.filter(r => !projectRepos.some(p => p.id === r.id));
|
|
438
|
+
const handleConnected = connected => {
|
|
439
|
+
setExtraRepos(prev => prev.some(r => r.id === connected.id) ? prev : [...prev, connected]);
|
|
440
|
+
// The repository just connected becomes the selection in the picker.
|
|
441
|
+
setRepo(connected.id);
|
|
442
|
+
};
|
|
443
|
+
const renderRepositoryField = () => /*#__PURE__*/React.createElement("div", {
|
|
444
|
+
className: "lk-field"
|
|
445
|
+
}, /*#__PURE__*/React.createElement(Label, {
|
|
446
|
+
size: "small",
|
|
447
|
+
className: "lk-label"
|
|
448
|
+
}, "Repository"), /*#__PURE__*/React.createElement(RepositorySelect, {
|
|
449
|
+
repositories: projectRepos,
|
|
450
|
+
connections: CONNECTIONS,
|
|
451
|
+
selected: repo,
|
|
452
|
+
onChange: setRepo
|
|
453
|
+
}), /*#__PURE__*/React.createElement(Caption1, {
|
|
454
|
+
color: "tertiary",
|
|
455
|
+
className: "lk-repo-hint"
|
|
456
|
+
}, "Only repositories connected to this project are listed.", " ", /*#__PURE__*/React.createElement("button", {
|
|
457
|
+
type: "button",
|
|
458
|
+
className: "lk-repo-link",
|
|
459
|
+
onClick: () => setConnectOpen(true)
|
|
460
|
+
}, "Connect a repository"), " ", "if the one you need is missing."));
|
|
461
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Dialog, {
|
|
462
|
+
open: open,
|
|
463
|
+
onClose: close,
|
|
464
|
+
disableCloseOnEsc: true
|
|
465
|
+
}, /*#__PURE__*/React.createElement(MenuGlobalStyle, {
|
|
466
|
+
$menuWidth: menuWidth
|
|
467
|
+
}), /*#__PURE__*/React.createElement(Dialog.Title, null, "Link Branch or Pull Request"), /*#__PURE__*/React.createElement(Dialog.ContentDivider, null), /*#__PURE__*/React.createElement(Dialog.Content, null, /*#__PURE__*/React.createElement(StyledLinkBody, null, loading ? /*#__PURE__*/React.createElement("div", {
|
|
468
|
+
className: "lk-skeleton"
|
|
469
|
+
}, /*#__PURE__*/React.createElement("div", {
|
|
470
|
+
className: "sk-row"
|
|
471
|
+
}, /*#__PURE__*/React.createElement(SkeletonLoader, {
|
|
472
|
+
className: "sk-choose"
|
|
473
|
+
})), /*#__PURE__*/React.createElement("div", {
|
|
474
|
+
className: "sk-row"
|
|
475
|
+
}, /*#__PURE__*/React.createElement(SkeletonLoader, {
|
|
476
|
+
className: "sk-label"
|
|
477
|
+
}), /*#__PURE__*/React.createElement(SkeletonLoader, {
|
|
478
|
+
className: "sk-control"
|
|
479
|
+
}))) : /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(ChooseV2, {
|
|
480
|
+
required: true,
|
|
481
|
+
options: MODE_OPTIONS,
|
|
482
|
+
selected: [mode],
|
|
483
|
+
onChange: ids => changeMode(ids[0])
|
|
484
|
+
}), /*#__PURE__*/React.createElement("div", {
|
|
485
|
+
className: "lk-tabbody"
|
|
486
|
+
}, mode === "existing" ? /*#__PURE__*/React.createElement("div", {
|
|
487
|
+
className: "lk-field",
|
|
488
|
+
ref: fieldRef
|
|
489
|
+
}, /*#__PURE__*/React.createElement(Label, {
|
|
490
|
+
size: "small",
|
|
491
|
+
className: "lk-label",
|
|
492
|
+
invalid: existingInvalid
|
|
493
|
+
}, "Branch or Pull Request"), /*#__PURE__*/React.createElement(Select, {
|
|
494
|
+
options: GROUPED_OPTIONS,
|
|
495
|
+
selected: selected === null ? undefined : selected,
|
|
496
|
+
onChange: v => setSelected(v),
|
|
497
|
+
placeholder: "Search branches and pull requests",
|
|
498
|
+
selectClassName: "lk-existing-select-menu",
|
|
499
|
+
onSelectOpen: measureMenu,
|
|
500
|
+
disabledInternalSort: true,
|
|
501
|
+
forceCloseMenu: true,
|
|
502
|
+
target: /*#__PURE__*/React.createElement(SelectTrigger, {
|
|
503
|
+
className: "lk-control",
|
|
504
|
+
invalid: existingInvalid,
|
|
505
|
+
typographyProps: selected === null ? {
|
|
506
|
+
color: "tertiary"
|
|
507
|
+
} : undefined
|
|
508
|
+
}, selectedLabel)
|
|
509
|
+
})) : mode === "branch" ? /*#__PURE__*/React.createElement(React.Fragment, null, renderRepositoryField(), /*#__PURE__*/React.createElement("div", {
|
|
510
|
+
className: "lk-field"
|
|
511
|
+
}, /*#__PURE__*/React.createElement(Label, {
|
|
512
|
+
size: "small",
|
|
513
|
+
className: "lk-label",
|
|
514
|
+
invalid: branchInvalid
|
|
515
|
+
}, "Branch Name"), /*#__PURE__*/React.createElement(Input, {
|
|
516
|
+
className: "lk-control",
|
|
517
|
+
value: branchName,
|
|
518
|
+
invalid: branchInvalid,
|
|
519
|
+
onChange: e => setBranchName(e.target.value)
|
|
520
|
+
})), /*#__PURE__*/React.createElement("div", {
|
|
521
|
+
className: "lk-field"
|
|
522
|
+
}, /*#__PURE__*/React.createElement(Label, {
|
|
523
|
+
size: "small",
|
|
524
|
+
className: "lk-label"
|
|
525
|
+
}, "Create From"), /*#__PURE__*/React.createElement(BranchSelect, {
|
|
526
|
+
options: baseBranchOptions(repo),
|
|
527
|
+
selected: createFrom,
|
|
528
|
+
onChange: setCreateFrom,
|
|
529
|
+
placeholder: "Select base branch"
|
|
530
|
+
}))) : /*#__PURE__*/React.createElement(React.Fragment, null, renderRepositoryField(), /*#__PURE__*/React.createElement("div", {
|
|
531
|
+
className: "lk-field"
|
|
532
|
+
}, /*#__PURE__*/React.createElement(Label, {
|
|
533
|
+
size: "small",
|
|
534
|
+
className: "lk-label"
|
|
535
|
+
}, "Source Branch"), /*#__PURE__*/React.createElement(BranchSelect, {
|
|
536
|
+
options: sourceBranchOptions(repo),
|
|
537
|
+
selected: sourceBranch,
|
|
538
|
+
onChange: setSourceBranch,
|
|
539
|
+
placeholder: "Select source branch"
|
|
540
|
+
})), /*#__PURE__*/React.createElement("div", {
|
|
541
|
+
className: "lk-field"
|
|
542
|
+
}, /*#__PURE__*/React.createElement(Label, {
|
|
543
|
+
size: "small",
|
|
544
|
+
className: "lk-label"
|
|
545
|
+
}, "Merge Into"), /*#__PURE__*/React.createElement(BranchSelect, {
|
|
546
|
+
options: baseBranchOptions(repo),
|
|
547
|
+
selected: mergeInto,
|
|
548
|
+
onChange: setMergeInto,
|
|
549
|
+
placeholder: "Select base branch"
|
|
550
|
+
})), /*#__PURE__*/React.createElement("div", {
|
|
551
|
+
className: "lk-field"
|
|
552
|
+
}, /*#__PURE__*/React.createElement(Label, {
|
|
553
|
+
size: "small",
|
|
554
|
+
className: "lk-label",
|
|
555
|
+
invalid: titleInvalid
|
|
556
|
+
}, "Title"), /*#__PURE__*/React.createElement(Input, {
|
|
557
|
+
className: "lk-control",
|
|
558
|
+
value: prTitle,
|
|
559
|
+
invalid: titleInvalid,
|
|
560
|
+
onChange: e => setPrTitle(e.target.value)
|
|
561
|
+
}))))))), /*#__PURE__*/React.createElement(Dialog.ContentDivider, null), /*#__PURE__*/React.createElement(Dialog.Actions, null, /*#__PURE__*/React.createElement(Button, {
|
|
562
|
+
variant: "primary",
|
|
563
|
+
style: {
|
|
564
|
+
marginRight: 12
|
|
565
|
+
},
|
|
566
|
+
disabled: loading,
|
|
567
|
+
onClick: handleSubmit
|
|
568
|
+
}, primaryLabel), /*#__PURE__*/React.createElement(Button, {
|
|
569
|
+
variant: "secondary",
|
|
570
|
+
onClick: close
|
|
571
|
+
}, "Cancel"))), /*#__PURE__*/React.createElement(ConnectRepositoryDialog, {
|
|
572
|
+
open: connectOpen,
|
|
573
|
+
onClose: () => setConnectOpen(false),
|
|
574
|
+
onConnect: handleConnected,
|
|
575
|
+
repositories: connectableRepos,
|
|
576
|
+
connections: CONNECTIONS
|
|
577
|
+
}));
|
|
578
|
+
};
|
|
579
|
+
//# sourceMappingURL=LinkBranchOrPullRequestDialog.js.map
|