@activecollab/components
Version:
ActiveCollab Components
1,386 lines • 54.2 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.Spine = exports.SourceCodeSection = exports.IssueRow = exports.HistoryDialog = exports.CompletedHeader = exports.CodeRow = void 0;
var _react = _interopRequireWildcard(require("react"));
var _styledComponents = _interopRequireWildcard(require("styled-components"));
var _LinkBranchOrPullRequestDialog = require("./LinkBranchOrPullRequestDialog");
var _LinkingCommandsButton = require("./LinkingCommandsButton");
var _RoundAvatar = require("./RoundAvatar");
var _tokens = require("./tokens");
var _AvatarGroup = require("../../components/AvatarGroup");
var _Button = require("../../components/Button");
var _AddToListButton = require("../../components/Button/AddToListButton");
var _Chip = require("../../components/Chip");
var _Dialog = require("../../components/Dialog");
var _IconButton = require("../../components/IconButton");
var _Icons = require("../../components/Icons");
var _StepSequence = require("../../components/StepSequence");
var _Tooltip = require("../../components/Tooltip");
var _Typography = require("../../components/Typography");
var _utils = require("../../utils");
var _excluded = ["size", "bg", "initials", "alt"];
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t in e) "default" !== _t && {}.hasOwnProperty.call(e, _t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t)) && (i.get || i.set) ? o(f, _t, i) : f[_t] = e[_t]); return f; })(e, t); }
function _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
function _arrayWithHoles(r) { if (Array.isArray(r)) return r; }
function _objectWithoutProperties(e, t) { if (null == e) return {}; var o, r, i = _objectWithoutPropertiesLoose(e, t); if (Object.getOwnPropertySymbols) { var n = Object.getOwnPropertySymbols(e); for (r = 0; r < n.length; r++) o = n[r], -1 === t.indexOf(o) && {}.propertyIsEnumerable.call(e, o) && (i[o] = e[o]); } return i; }
function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (-1 !== e.indexOf(n)) continue; t[n] = r[n]; } return t; }
function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
/**
* Source Code section of a task — the shared subsystem behind the
* `Presentation/Source/Task Source` stories (Mix / All Open / All Completed).
* Holds the row types (issue / pull-or-merge request / branch), the pipeline
* spine, the history dialog, and the section that lays them out. Extracted into
* `shared/` so all three stories render the same components; editing a row type
* here updates every story at once.
*/
var SANS = '-apple-system, BlinkMacSystemFont, "Roboto", "Helvetica Neue", Arial, sans-serif';
/* Icons in the collection colour either via `stroke` (outline glyphs whose root
is `fill="none"`) or via `fill`. To tint a history glyph by tone we must set
the right one — this set marks the stroke-based glyphs used in the stream. */
var STROKE_ICONS = new Set([_Icons.GitBranchIcon, _Icons.GitCommitIcon, _Icons.GitPullRequestIcon, _Icons.GitPullRequestDraftIcon, _Icons.GitPullRequestClosedIcon, _Icons.GitMergeIcon, _Icons.GearIcon, _Icons.GearFailedIcon, _Icons.CloudDeployIcon, _Icons.CloudDeployFailedIcon, _Icons.GitRepositoryIcon]);
/** Every event glyph renders in the standard muted gray; success / failure is
carried by a trailing check / cross after the title instead of the glyph. */
var iconColorProps = function iconColorProps(icon) {
return STROKE_ICONS.has(icon) ? {
stroke: "var(--color-theme-600)"
} : {
fill: "var(--color-theme-600)"
};
};
/* ================================================================== */
/* Issue state glyphs (open / closed) — mirror the app's IssueStateIcon */
/* (`CircleDotIcon` when open, filled `CheckboxBlankTogglerIcon` when */
/* closed). Kept as a helper so the row lead and the status chip share */
/* the same glyph. */
/* ================================================================== */
var IssueStateIcon = function IssueStateIcon(_ref) {
var closed = _ref.closed,
_ref$size = _ref.size,
size = _ref$size === void 0 ? 16 : _ref$size;
return closed ? /*#__PURE__*/_react.default.createElement(_Icons.CheckboxBlankTogglerIcon, {
width: size,
height: size,
fill: "var(--color-primary)"
}) : /*#__PURE__*/_react.default.createElement(_Icons.CircleDotIcon, {
width: size,
height: size
});
};
/* ================================================================== */
/* Source Code section — data model */
/* ================================================================== */
var STAGE_NAMES = ["Branch", "Commits", "Pull request", "CI / Build", "Deploy"];
var MONTHS = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
var pad = function pad(n) {
return String(n).padStart(2, "0");
};
/**
* Reproduces ActiveCollab's standard `Ago` component (`Angie.functions.ago()`)
* for the mock: "Just now", "N minutes ago", "Today HH:mm", "Yesterday HH:mm",
* "MMM D. HH:mm", else "MMM D. YYYY HH:mm". Production must use the real one,
* which also carries the absolute timestamp in a tooltip and auto-refreshes.
*/
var formatAgo = function formatAgo(minutesAgo) {
var now = new Date();
var then = new Date(now.getTime() - minutesAgo * 60000);
if (minutesAgo < 2) {
return "Just now";
}
if (minutesAgo < 60) {
return "".concat(Math.floor(minutesAgo), " minutes ago");
}
var time = "".concat(pad(then.getHours()), ":").concat(pad(then.getMinutes()));
if (then.toDateString() === now.toDateString()) {
return "Today ".concat(time);
}
var yesterday = new Date(now.getTime() - 24 * 60 * 60000);
if (then.toDateString() === yesterday.toDateString()) {
return "Yesterday ".concat(time);
}
var monthDay = "".concat(MONTHS[then.getMonth()], " ").concat(then.getDate(), ".");
if (then.getFullYear() === now.getFullYear()) {
return "".concat(monthDay, " ").concat(time);
}
return "".concat(monthDay, " ").concat(then.getFullYear(), " ").concat(time);
};
/** A VCS issue. Weakly referenced by any number of branches / PRs. */
/** A branch or pull request read from the VCS. */
var mkStages = function mkStages(defs) {
return defs.map(function (d, i) {
return _objectSpread({
name: STAGE_NAMES[i]
}, d);
});
};
var issueCompleted = function issueCompleted(i) {
return i.state === "closed";
};
var codeCompleted = function codeCompleted(e) {
return e.status !== "open";
};
var byRecency = function byRecency(a, b) {
return a.updatedMinsAgo - b.updatedMinsAgo;
};
/** External URL for an element — opens the object in the provider (new tab). */
var issueUrl = function issueUrl(i) {
return "https://github.com/".concat(i.repoFull, "/issues/").concat(i.ref.replace("#", ""));
};
var codeUrl = function codeUrl(e) {
if (e.kind === "pr") {
var _e$title$match$, _e$title$match;
var number = (_e$title$match$ = (_e$title$match = e.title.match(/#(\d+)/)) === null || _e$title$match === void 0 ? void 0 : _e$title$match[1]) !== null && _e$title$match$ !== void 0 ? _e$title$match$ : "";
return "https://github.com/".concat(e.repoFull, "/pull/").concat(number);
}
return "https://github.com/".concat(e.repoFull, "/tree/").concat(e.title);
};
/* ---- Issues -------------------------------------------------------- */
var ISSUES = [{
ref: "#482",
title: "#482 Ranks reset when a contract is archived",
repo: "backend",
repoFull: "activecollab/backend",
state: "open",
updatedLabel: "20m ago",
updatedMinsAgo: 20
}, {
ref: "#455",
title: "#455 Retainer totals off by a rounding cent",
repo: "backend",
repoFull: "activecollab/backend",
state: "open",
updatedLabel: "3h ago",
updatedMinsAgo: 180
}, {
ref: "#470",
title: "#470 Cannot set a rank above 100",
repo: "backend",
repoFull: "activecollab/backend",
state: "closed",
updatedLabel: "4d ago",
updatedMinsAgo: 5760
}];
/* ---- Branches / pull requests -------------------------------------- */
var CODE_ENTRIES = [{
// Open PR with a pipeline mid-run: the CI / Build stage is "progress"
// (blue node, white dot) while Deploy is still "todo". This is the one
// state note 02 describes but the other examples never show — a healthy
// task that is currently *doing something*, visible at a glance on the
// spine. The connector into Build turns green (movement into the stage);
// the connector into Deploy stays muted.
kind: "pr",
title: "#119921 Recalculate ranks when a contract is archived",
headSha: "3d5a8f1c9b7e2604a1f8c3d5e6079b2a4c6d8e0f",
repo: "backend",
repoFull: "activecollab/backend",
status: "open",
sourceBranch: "fix/rank-archive-482",
targetBranch: "main",
closing: true,
contributors: [{
initials: "DA",
bg: _tokens.AVATAR_COLORS.green
}],
commits: {
value: 8,
tip: "8 commits · last 1h ago by Dragana A."
},
diff: {
add: 96,
del: 12,
tip: "96 additions, 12 deletions across 5 files"
},
comments: {
value: 2,
tip: "2 comments on the pull request"
},
updatedLabel: "10m ago",
updatedMinsAgo: 10,
references: ["#482"],
stages: mkStages([{
state: "done",
details: ["fix/rank-archive-482", "on activecollab/backend"]
}, {
state: "done",
details: ["8 commits", "last 1h ago by Dragana A."]
}, {
state: "done",
details: ["#119921 opened", "awaiting review"]
}, {
state: "progress",
details: ["Build running", "CI pipeline #501 in progress"]
}, {
state: "todo",
details: ["Not deployed"]
}]),
pipelineSupported: true,
history: [{
icon: _Icons.GitBranchIcon,
title: "Branch created",
detail: "fix/rank-archive-482 by Dragana A.",
minutesAgo: 600
}, {
icon: _Icons.GitCommitIcon,
title: "8 commits pushed",
detail: "Last by Dragana A.: “Recalculate ranks on contract archive”",
minutesAgo: 90
}, {
icon: _Icons.GitPullRequestIcon,
title: "Pull request opened",
detail: "Target: main by Dragana A.",
minutesAgo: 40,
tone: "progress"
}, {
icon: _Icons.EyeIcon,
title: "Review requested",
detail: "Requested by Ilija S. and Marko K.",
minutesAgo: 30
}, {
icon: _Icons.GearIcon,
title: "Build started",
detail: "CI pipeline #501",
minutesAgo: 10,
tone: "progress"
}]
}, {
kind: "branch",
title: "spike/rank-cache",
headSha: "9f3c1a2b7d4e5f60819a2b3c4d5e6f7081920304",
repo: "backend",
repoFull: "activecollab/backend",
status: "open",
contributors: [{
initials: "IS",
bg: _tokens.AVATAR_COLORS.purple
}],
commits: {
value: 1,
tip: "1 commit · 30m ago by Ilija S."
},
diff: {
add: 38,
del: 4,
tip: "38 additions, 4 deletions across 2 files"
},
noPrLabel: "no pull request yet",
updatedLabel: "30m ago",
updatedMinsAgo: 30,
references: [],
stages: mkStages([{
state: "done",
details: ["spike/rank-cache", "on activecollab/backend"]
}, {
state: "done",
details: ["1 commit", "30m ago by Ilija S."]
}, {
state: "todo",
details: ["No pull request opened yet"]
}]),
pipelineSupported: false,
history: [{
icon: _Icons.GitBranchIcon,
title: "Branch created",
detail: "spike/rank-cache by Ilija Studen",
minutesAgo: 120
}, {
icon: _Icons.GitCommitIcon,
title: "One commit pushed",
detail: "Ilija Studen: “Prototype rank cache”",
minutesAgo: 30
}]
}, {
kind: "branch",
title: "feature/retainers-ui-34",
headSha: "4a7b9c2d1e3f5061728394a5b6c7d8e9f0a1b2c3",
repo: "frontend",
repoFull: "activecollab/frontend",
status: "open",
contributors: [{
initials: "DA",
bg: _tokens.AVATAR_COLORS.green
}],
commits: {
value: 6,
tip: "6 commits · last 1h ago by Dragana A."
},
diff: {
add: 214,
del: 52,
tip: "214 additions, 52 deletions across 9 files"
},
noPrLabel: "no pull request yet",
updatedLabel: "1h ago",
updatedMinsAgo: 60,
references: ["#482"],
stages: mkStages([{
state: "done",
details: ["feature/retainers-ui-34", "on activecollab/frontend"]
}, {
state: "done",
details: ["6 commits", "last 1h ago by Dragana A."]
}, {
state: "todo",
details: ["No pull request opened yet"]
}, {
state: "todo",
details: ["No build yet"]
}, {
state: "todo",
details: ["Not deployed"]
}]),
pipelineSupported: true,
history: [{
icon: _Icons.GitBranchIcon,
title: "Branch created",
detail: "feature/retainers-ui-34 by Dragana A.",
minutesAgo: 480
}, {
icon: _Icons.GitCommitIcon,
title: "6 commits pushed",
detail: "Last by Dragana A.: “Retainer settings screen”",
minutesAgo: 60
}]
}, {
kind: "pr",
title: "#119915 Contract UI rank controls",
headSha: "b2c3d4e5f60718293a4b5c6d7e8f90a1b2c3d4e5",
repo: "frontend",
repoFull: "activecollab/frontend",
status: "merged",
sourceBranch: "feature/contracts-ui-34",
targetBranch: "main",
closing: true,
contributors: [{
initials: "MK",
bg: _tokens.AVATAR_COLORS.blue
}],
commits: {
value: 11,
tip: "11 commits · last 5h ago by Marko K."
},
diff: {
add: 168,
del: 24,
tip: "168 additions, 24 deletions across 6 files"
},
comments: {
value: 5,
tip: "5 comments on the pull request"
},
updatedLabel: "5h ago",
updatedMinsAgo: 300,
references: ["#455"],
stages: mkStages([{
state: "done",
details: ["feature/contracts-ui-34", "on activecollab/frontend"]
}, {
state: "done",
details: ["11 commits", "last 5h ago by Marko K."]
}, {
state: "done",
details: ["#119915 merged", "approved by 1 reviewer"]
}, {
state: "failed",
details: ["Build failing", "3 of 12 checks failed"]
}, {
state: "todo",
details: ["Not deployed"]
}]),
pipelineSupported: true,
history: [{
icon: _Icons.GitBranchIcon,
title: "Branch created",
detail: "feature/contracts-ui-34 by Marko K.",
minutesAgo: 11520
}, {
icon: _Icons.GitCommitIcon,
title: "6 commits pushed",
detail: "Last by Marko K.: “Wire rank controls to contracts API”",
minutesAgo: 10080
}, {
icon: _Icons.GitPullRequestDraftIcon,
title: "Draft pull request opened",
detail: "Target: main by Marko K.",
minutesAgo: 8640
}, {
icon: _Icons.GearIcon,
title: "Build started",
detail: "CI pipeline #479",
minutesAgo: 8639,
tone: "progress"
}, {
icon: _Icons.GearFailedIcon,
title: "Build failed",
detail: "3 of 12 checks failed",
minutesAgo: 8635,
tone: "danger"
}, {
icon: _Icons.GitCommitIcon,
title: "2 commits pushed",
detail: "Last by Marko K.: “Fix failing snapshot tests”",
minutesAgo: 7200
}, {
icon: _Icons.GearIcon,
title: "Build passed",
detail: "All 12 checks passed · CI pipeline #482",
minutesAgo: 7195,
tone: "success"
}, {
icon: _Icons.GitPullRequestIcon,
title: "Marked ready for review",
author: "Marko K.",
minutesAgo: 5760,
tone: "progress"
}, {
icon: _Icons.EyeIcon,
title: "Review requested",
detail: "Requested by Ana P., Ilija S. and 2 more",
minutesAgo: 5755
}, {
icon: _Icons.MessageIcon,
title: "Changes requested",
detail: "Request on 4 files by Ana P.",
minutesAgo: 4320
}, {
icon: _Icons.GitCommitIcon,
title: "One commit pushed",
detail: "Marko K.: “Address review feedback”",
minutesAgo: 4000
}, {
icon: _Icons.GitPullRequestClosedIcon,
title: "Pull request closed",
detail: "Closed without merging by Marko K.",
minutesAgo: 2880
}, {
icon: _Icons.GitPullRequestIcon,
title: "Pull request reopened",
detail: "Target: main by Marko K.",
minutesAgo: 1680,
tone: "progress"
}, {
icon: _Icons.GitCommitIcon,
title: "4 commits pushed",
detail: "Last by Marko K.: “Rebuild rank controls with a new segmented layout, keyboard navigation, and analytics events”",
minutesAgo: 1560
}, {
icon: _Icons.CloudDeployIcon,
title: "Deployed to staging",
detail: "Release ci-4821",
minutesAgo: 300,
tone: "success"
}, {
icon: _Icons.CheckIcon,
title: "Approved",
detail: "2 approvals · Ana P., Ilija S.",
minutesAgo: 180,
tone: "success"
}, {
icon: _Icons.GitMergeIcon,
title: "Pull request merged",
detail: "Target: main by Marko K.",
minutesAgo: 38,
tone: "success"
}, {
icon: _Icons.CloudDeployFailedIcon,
title: "Deploy failed",
detail: "Target: production by Marko K.",
minutesAgo: 24,
tone: "danger"
}, {
icon: _Icons.CloudDeployIcon,
title: "Deployed to production",
detail: "Release v2026.7.3",
minutesAgo: 1,
tone: "success"
}]
}, {
kind: "branch",
title: "feature/retainers-34",
headSha: "1a2b3c4d5e6f708192a3b4c5d6e7f8091a2b3c4d",
repo: "backend",
repoFull: "activecollab/backend",
status: "merged",
contributors: [{
initials: "IS",
bg: _tokens.AVATAR_COLORS.purple
}],
commits: {
value: 14,
tip: "14 commits · merged 2d ago by Ilija S."
},
diff: {
add: 405,
del: 37,
tip: "405 additions, 37 deletions across 11 files"
},
updatedLabel: "2d ago",
updatedMinsAgo: 2880,
references: ["#482", "#470"],
stages: mkStages([{
state: "done",
details: ["feature/retainers-34", "on activecollab/backend"]
}, {
state: "done",
details: ["14 commits", "merged 2d ago by Ilija S."]
}, {
state: "done",
details: ["Merged via #119909", "into main"]
}]),
pipelineSupported: false,
history: [{
icon: _Icons.GitBranchIcon,
title: "Branch created",
detail: "feature/retainers-34 by Ilija Studen",
minutesAgo: 4320
}, {
icon: _Icons.GitCommitIcon,
title: "14 commits pushed",
detail: "Last by Ilija Studen: “Rank model + datastore updates”",
minutesAgo: 3000
}, {
icon: _Icons.GitMergeIcon,
title: "Branch merged",
detail: "Target: main by Ilija Studen",
minutesAgo: 2880,
tone: "success"
}]
}, {
kind: "pr",
title: "#119909 Allow and update ranks across datastores",
headSha: "c4d5e6f70819202a3b4c5d6e7f8091a2b3c4d5e6",
repo: "backend",
repoFull: "activecollab/backend",
status: "merged",
sourceBranch: "feature/retainers-34",
targetBranch: "main",
contributors: [{
initials: "IS",
bg: _tokens.AVATAR_COLORS.purple
}, {
initials: "MK",
bg: _tokens.AVATAR_COLORS.blue
}],
commits: {
value: 14,
tip: "14 commits · merged 2d ago by Ilija S."
},
diff: {
add: 405,
del: 37,
tip: "405 additions, 37 deletions across 11 files"
},
comments: {
value: 12,
tip: "12 comments on the pull request"
},
updatedLabel: "2d ago",
updatedMinsAgo: 2900,
references: ["#482", "#470"],
stages: mkStages([{
state: "done",
details: ["feature/retainers-34", "on activecollab/backend"]
}, {
state: "done",
details: ["14 commits", "last 2d ago by Ilija S."]
}, {
state: "done",
details: ["#119909 merged", "approved by 2 reviewers"]
}]),
pipelineSupported: false,
history: [{
icon: _Icons.GitPullRequestIcon,
title: "Pull request opened",
detail: "Target: main by Ilija Studen",
minutesAgo: 3000,
tone: "progress"
}, {
icon: _Icons.CheckIcon,
title: "Approved",
detail: "2 approvals · Marko K., Janko S.",
minutesAgo: 2905,
tone: "success"
}, {
icon: _Icons.GitMergeIcon,
title: "Pull request merged",
detail: "Target: main by Ilija Studen",
minutesAgo: 2880,
tone: "success"
}]
}, {
kind: "branch",
title: "hotfix/rank-typo",
headSha: "7e8f90a1b2c3d4e5f60718293a4b5c6d7e8f9012",
repo: "backend",
repoFull: "activecollab/backend",
status: "deleted",
contributors: [{
initials: "MK",
bg: _tokens.AVATAR_COLORS.blue
}],
commits: {
value: 2,
tip: "2 commits · deleted 5d ago"
},
diff: {
add: 6,
del: 3,
tip: "6 additions, 3 deletions across 1 file"
},
updatedLabel: "5d ago",
updatedMinsAgo: 7000,
references: ["#470"],
stages: mkStages([{
state: "done",
details: ["hotfix/rank-typo", "on activecollab/backend"]
}, {
state: "done",
details: ["2 commits", "by Marko K."]
}, {
state: "todo",
details: ["No pull request opened"]
}]),
pipelineSupported: false,
history: [{
icon: _Icons.GitBranchIcon,
title: "Branch created",
detail: "hotfix/rank-typo by Marko K.",
minutesAgo: 8640
}, {
icon: _Icons.GitCommitIcon,
title: "2 commits pushed",
detail: "Last by Marko K.: “Fix rank label typo”",
minutesAgo: 8600
}, {
icon: _Icons.TrashIcon,
title: "Branch deleted",
detail: "Soft deleted by Marko K.",
minutesAgo: 7000
}]
}, {
kind: "pr",
title: "#119870 Clamp rank to valid range",
headSha: "d5e6f708192a3b4c5d6e7f8091a2b3c4d5e6f701",
repo: "backend",
repoFull: "activecollab/backend",
status: "merged",
sourceBranch: "fix/rank-clamp-33",
targetBranch: "main",
contributors: [{
initials: "MK",
bg: _tokens.AVATAR_COLORS.blue
}],
commits: {
value: 4,
tip: "4 commits · merged 5d ago by Marko K."
},
diff: {
add: 52,
del: 8,
tip: "52 additions, 8 deletions across 3 files"
},
updatedLabel: "5d ago",
updatedMinsAgo: 7200,
references: ["#470"],
stages: mkStages([{
state: "done",
details: ["fix/rank-clamp-33", "on activecollab/backend"]
}, {
state: "done",
details: ["4 commits", "merged 5d ago by Marko K."]
}, {
state: "done",
details: ["#119870 merged", "approved by 1 reviewer"]
}]),
pipelineSupported: false,
history: [{
icon: _Icons.GitBranchIcon,
title: "Branch created",
detail: "fix/rank-clamp-33 by Marko K.",
minutesAgo: 8640
}, {
icon: _Icons.GitPullRequestIcon,
title: "Pull request opened",
detail: "Target: main by Marko K.",
minutesAgo: 8600,
tone: "progress"
}, {
icon: _Icons.GitMergeIcon,
title: "Pull request merged",
detail: "Target: main by Marko K.",
minutesAgo: 7200,
tone: "success"
}]
}, {
kind: "pr",
title: "#119888 Cache ranks per datastore",
headSha: "a1b2c3d4e5f60718293a4b5c6d7e8f90a1b2c3d4",
repo: "backend",
repoFull: "activecollab/backend",
status: "closed",
sourceBranch: "feature/rank-datastore-cache",
targetBranch: "main",
contributors: [{
initials: "IS",
bg: _tokens.AVATAR_COLORS.purple
}],
commits: {
value: 5,
tip: "5 commits · closed 3d ago by Ilija S."
},
diff: {
add: 120,
del: 15,
tip: "120 additions, 15 deletions across 4 files"
},
comments: {
value: 3,
tip: "3 comments on the pull request"
},
updatedLabel: "3d ago",
updatedMinsAgo: 4320,
references: ["#455"],
stages: mkStages([{
state: "done",
details: ["feature/rank-datastore-cache", "on activecollab/backend"]
}, {
state: "done",
details: ["5 commits", "last 3d ago by Ilija S."]
}, {
state: "todo",
details: ["#119888 closed without merging"]
}]),
pipelineSupported: false,
history: [{
icon: _Icons.GitPullRequestIcon,
title: "Pull request opened",
detail: "Target: main by Ilija Studen",
minutesAgo: 5760,
tone: "progress"
}, {
icon: _Icons.GitPullRequestClosedIcon,
title: "Pull request closed",
detail: "Closed without merging by Ilija Studen",
minutesAgo: 4320
}]
}];
/* ================================================================== */
/* Spine + history dialog (for branches / pull requests) */
/* ================================================================== */
var StageTip = function StageTip(_ref2) {
var name = _ref2.name,
details = _ref2.details;
return /*#__PURE__*/_react.default.createElement("span", {
style: {
display: "block",
textAlign: "left",
lineHeight: 1.5
}
}, /*#__PURE__*/_react.default.createElement("span", {
style: {
display: "block",
fontWeight: 700
}
}, "Stage: ", name), details.map(function (d, i) {
return /*#__PURE__*/_react.default.createElement("span", {
key: "".concat(name, "-").concat(i),
style: {
display: "block"
}
}, d);
}));
};
var StyledSpineSequence = (0, _styledComponents.default)(_StepSequence.StepSequence).withConfig({
displayName: "SourceCodeSection__StyledSpineSequence",
componentId: "sc-rvqbh5-0"
})(["align-self:center;flex-shrink:0;"]);
/** Stage state → the generic look `StepSequence` renders it with. */
var STAGE_STEP = {
done: {
tone: "success",
fill: "solid",
icon: /*#__PURE__*/_react.default.createElement(_Icons.CheckIcon, {
fill: "var(--only-white)",
width: 14,
height: 14
})
},
progress: {
tone: "info",
fill: "solid"
},
failed: {
tone: "danger",
fill: "solid",
icon: /*#__PURE__*/_react.default.createElement(_Icons.CloseIcon, {
fill: "var(--only-white)",
width: 12,
height: 12
})
},
todo: {
tone: "neutral",
fill: "outline"
}
};
var Spine = exports.Spine = function Spine(_ref3) {
var items = _ref3.items,
onClick = _ref3.onClick;
return /*#__PURE__*/_react.default.createElement(StyledSpineSequence, {
ariaLabel: "Open source code history",
onClick: onClick,
steps: items.map(function (s) {
return _objectSpread(_objectSpread({}, STAGE_STEP[s.state]), {}, {
key: s.name,
tooltip: /*#__PURE__*/_react.default.createElement(StageTip, s)
});
})
});
};
/* The whole content scrolls together (header + stream + note) once the stream
is long — the dialog title bar stays fixed, everything below scrolls. */
var StyledHistory = _styledComponents.default.div.withConfig({
displayName: "SourceCodeSection__StyledHistory",
componentId: "sc-rvqbh5-1"
})(["font-family:", ";max-height:60vh;overflow-y:auto;padding-right:4px;.hist-header{padding-bottom:20px;margin-bottom:20px;border-bottom:1px solid var(--border-primary);}.hist-name{display:flex;align-items:center;gap:8px;flex-wrap:wrap;}.hist-branches{display:flex;align-items:center;gap:6px;flex-wrap:wrap;margin-top:8px;font-size:13px;color:var(--color-theme-600);}.hist-branch{display:inline-flex;align-items:center;gap:4px;}.hist-repo{display:inline-flex;align-items:center;gap:4px;margin-top:6px;font-size:13px;color:var(--color-theme-600);}.sc-chip{display:inline-flex;align-items:center;gap:3px;height:20px;padding:0 8px;border-radius:6px;font-size:11px;font-weight:700;letter-spacing:0.02em;flex-shrink:0;}.sc-chip.done{color:var(--color-primary);background:color-mix(in srgb,var(--color-primary) 15%,transparent);}.sc-chip.gone{color:var(--color-theme-900);background:var(--color-theme-200);border:1px solid var(--border-primary);}.sc-chip.fail{color:var(--red-alert);background:color-mix(in srgb,var(--red-alert) 15%,transparent);}.hist-event{display:flex;align-items:center;gap:12px;padding-bottom:20px;}.hist-event:last-child{padding-bottom:0;}.hist-icon{flex-shrink:0;width:22px;height:22px;display:flex;align-items:center;justify-content:center;}.hist-body{flex:1 1 auto;min-width:0;}.hist-title{display:flex;align-items:center;gap:6px;min-width:0;}.hist-title > *:first-child{min-width:0;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;}.hist-status{flex-shrink:0;display:inline-flex;}.hist-line{display:block;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;font-size:13px;line-height:1.5;color:var(--color-theme-600);}.hist-meta{flex-shrink:0;align-self:flex-start;text-align:right;white-space:nowrap;}.hist-note{display:flex;align-items:center;gap:6px;margin-top:16px;color:var(--color-theme-500);}.hist-note svg{flex-shrink:0;}"], SANS);
var HistoryDialog = exports.HistoryDialog = function HistoryDialog(_ref4) {
var entry = _ref4.entry,
onClose = _ref4.onClose;
return /*#__PURE__*/_react.default.createElement(_Dialog.Dialog, {
open: !!entry,
onClose: onClose,
enableBackgroundClick: true
}, /*#__PURE__*/_react.default.createElement(_Dialog.Dialog.Title, {
disableDefaultHeading: true
}, /*#__PURE__*/_react.default.createElement("div", {
style: {
display: "flex",
alignItems: "center",
justifyContent: "space-between",
gap: 12
}
}, /*#__PURE__*/_react.default.createElement(_Typography.Header3, null, (entry === null || entry === void 0 ? void 0 : entry.kind) === "branch" ? "Branch History" : "Pull Request History"), /*#__PURE__*/_react.default.createElement(_IconButton.IconButton, {
type: "button",
variant: "text gray",
onClick: onClose
}, /*#__PURE__*/_react.default.createElement(_Icons.CancelCrossIcon, null)))), /*#__PURE__*/_react.default.createElement(_Dialog.Dialog.ContentDivider, null), /*#__PURE__*/_react.default.createElement(_Dialog.Dialog.Content, null, entry && /*#__PURE__*/_react.default.createElement(StyledHistory, null, /*#__PURE__*/_react.default.createElement("div", {
className: "hist-header"
}, /*#__PURE__*/_react.default.createElement("div", {
className: "hist-name"
}, /*#__PURE__*/_react.default.createElement(_Typography.Body1, {
weight: "medium"
}, entry.status === "deleted" ? entry.title : /*#__PURE__*/_react.default.createElement(TitleLink, {
href: codeUrl(entry),
target: "_blank",
rel: "noopener noreferrer"
}, entry.title)), /*#__PURE__*/_react.default.createElement(CodeStatusChip, {
entry: entry
})), entry.kind === "pr" && entry.sourceBranch && entry.targetBranch && /*#__PURE__*/_react.default.createElement("div", {
className: "hist-branches"
}, /*#__PURE__*/_react.default.createElement("span", {
className: "hist-branch"
}, /*#__PURE__*/_react.default.createElement(_Icons.GitBranchIcon, {
width: 14,
height: 14
}), entry.sourceBranch), /*#__PURE__*/_react.default.createElement(_Icons.ArrowRightIcon, {
width: 14,
height: 14
}), /*#__PURE__*/_react.default.createElement("span", {
className: "hist-branch"
}, /*#__PURE__*/_react.default.createElement(_Icons.GitBranchIcon, {
width: 14,
height: 14
}), entry.targetBranch)), /*#__PURE__*/_react.default.createElement("span", {
className: "hist-repo"
}, /*#__PURE__*/_react.default.createElement(_Icons.GitRepositoryIcon, {
width: 14,
height: 14
}), entry.repoFull)), [...entry.history].sort(function (a, b) {
return a.minutesAgo - b.minutesAgo;
}).map(function (ev, i) {
return /*#__PURE__*/_react.default.createElement("div", {
className: "hist-event",
key: "".concat(ev.title, "-").concat(i)
}, /*#__PURE__*/_react.default.createElement("span", {
className: "hist-icon"
}, /*#__PURE__*/_react.default.createElement(ev.icon, _extends({
width: 22,
height: 22
}, iconColorProps(ev.icon)))), /*#__PURE__*/_react.default.createElement("div", {
className: "hist-body"
}, /*#__PURE__*/_react.default.createElement("div", {
className: "hist-title"
}, /*#__PURE__*/_react.default.createElement(_Typography.Body1, {
weight: "medium"
}, ev.title), ev.tone === "success" && /*#__PURE__*/_react.default.createElement("span", {
className: "hist-status"
}, /*#__PURE__*/_react.default.createElement(_Icons.CheckIcon, {
width: 16,
height: 16,
fill: "var(--color-sucess-green)"
})), ev.tone === "danger" && /*#__PURE__*/_react.default.createElement("span", {
className: "sc-chip fail"
}, /*#__PURE__*/_react.default.createElement(_Icons.CloseIcon, {
width: 12,
height: 12,
fill: "var(--red-alert)"
}), "Failed")), ev.detail && /*#__PURE__*/_react.default.createElement("span", {
className: "hist-line"
}, ev.detail), ev.author && /*#__PURE__*/_react.default.createElement("span", {
className: "hist-line"
}, ev.author)), /*#__PURE__*/_react.default.createElement("div", {
className: "hist-meta"
}, /*#__PURE__*/_react.default.createElement("span", {
className: "hist-line"
}, formatAgo(ev.minutesAgo))));
}), !entry.pipelineSupported && /*#__PURE__*/_react.default.createElement("div", {
className: "hist-note"
}, /*#__PURE__*/_react.default.createElement(_Icons.InfoSmallIcon, {
width: 15,
height: 15
}), /*#__PURE__*/_react.default.createElement(_Typography.Caption1, {
color: "secondary"
}, "No CI or deployment pipeline is configured for this repository.")))));
};
/* ================================================================== */
/* Source Code section — flat list, split open / completed */
/* ================================================================== */
var StyledSourceCode = _styledComponents.default.div.withConfig({
displayName: "SourceCodeSection__StyledSourceCode",
componentId: "sc-rvqbh5-2"
})(["font-family:", ";margin:0 0 16px;padding-bottom:16px;border-bottom:1px solid var(--border-primary);", " .sc-header{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-bottom:4px;}.sc-completed-row{display:flex;align-items:center;margin-top:8px;padding-top:8px;border-top:1px solid var(--border-primary);}.sc-add{margin-top:8px;padding-top:12px;border-top:1px solid var(--border-primary);}.sc-add .c--add-to-list-btn svg{box-sizing:content-box;}.sc-item{padding:12px 0;}.sc-item + .sc-item{border-top:1px solid var(--border-primary);}.sc-row{display:flex;align-items:flex-start;justify-content:space-between;gap:16px;}.sc-main{flex:1 1 0%;min-width:0;}.sc-name{display:flex;align-items:center;gap:8px;flex-wrap:nowrap;min-width:0;}.sc-lead{flex-shrink:0;display:inline-flex;color:var(--color-theme-600);}.sc-title{flex:0 1 auto;min-width:0;display:block;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;}.sc-title.strike{text-decoration:line-through;}.sc-title.strike-link{text-decoration:line-through;}.sc-title.strike-link:hover{text-decoration:none;}.sc-sigs{display:flex;align-items:center;gap:12px;flex-wrap:wrap;margin-top:10px;font-size:12px;color:var(--color-theme-600);}.sc-sig{display:inline-flex;align-items:center;gap:4px;}.sc-closing{display:inline-flex;align-items:center;flex-shrink:0;cursor:default;}.sc-sha{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;}.sc-muted{color:var(--color-theme-600);}.sc-refs{display:inline-flex;align-items:center;gap:6px;}.sc-refs .ref-link{color:var(--color-primary);font-weight:500;}"], SANS, function (p) {
return p.$flush && (0, _styledComponents.css)(["margin:0;padding-bottom:0;border-bottom:none;"]);
});
/* Element name — a link that opens the object in a new tab. Keeps the row's
typography (inherits color + weight), turns primary on hover, link cursor. */
var TitleLink = _styledComponents.default.a.withConfig({
displayName: "SourceCodeSection__TitleLink",
componentId: "sc-rvqbh5-3"
})(["color:inherit;text-decoration:none;cursor:pointer;transition:color 200ms ease;&:hover{color:var(--color-primary);}"]);
/* Status label chip — the DS `Chip` styled to match the app's
`SourceCodeStatusChip`: a "done" tone (primary text on a translucent-primary
fill) and a "gone" tone (muted text on a bordered theme-200 fill). */
var CHIP_BASE_STYLE = {
height: "1.25rem",
paddingLeft: "0.5rem",
paddingRight: "0.5rem",
borderRadius: "0.375rem",
gap: "3px",
flexShrink: 0
};
var CHIP_DONE_STYLE = _objectSpread(_objectSpread({}, CHIP_BASE_STYLE), {}, {
backgroundColor: "color-mix(in srgb, var(--color-primary) 15%, transparent)"
});
var CHIP_GONE_STYLE = _objectSpread(_objectSpread({}, CHIP_BASE_STYLE), {}, {
backgroundColor: "var(--color-theme-200)",
border: "1px solid var(--border-primary)"
});
/* Info tone — the default (blue) InfoBox recipe: blueSky tint + solid border. */
var CHIP_INFO_STYLE = _objectSpread(_objectSpread({}, CHIP_BASE_STYLE), {}, {
backgroundColor: "".concat(_utils.colors.blueSky.color, "1A"),
border: "1px solid ".concat(_utils.colors.blueSky.color)
});
var StatusChip = function StatusChip(_ref5) {
var label = _ref5.label,
tone = _ref5.tone,
glyph = _ref5.glyph;
return /*#__PURE__*/_react.default.createElement(_Chip.Chip, {
label: label,
startAdornment: glyph,
color: tone === "done" ? "var(--color-primary)" : tone === "info" ? _utils.colors.blueSky.lighter : undefined,
style: tone === "done" ? CHIP_DONE_STYLE : tone === "info" ? CHIP_INFO_STYLE : CHIP_GONE_STYLE,
typographyProps: {
variant: "Caption 1",
weight: "bold",
align: "center"
}
});
};
/* Contributor avatars — the app renders real user images through the DS
`AvatarGroup` (`ContributorAvatars.jsx`). The mock feeds that same component
initials avatars via `MockAvatar`, which honours AvatarGroup's cloneElement
contract (it injects `size`, `alt` and `style` — the overlap margin + paper
ring), so the grouping, overlap and "+N" overflow behave identically. */
var CONTRIBUTOR_NAMES = {
DA: "Dragana A.",
IS: "Ilija Studen",
MK: "Marko K."
};
var MockAvatar = /*#__PURE__*/_react.default.forwardRef(function (_ref6, ref) {
var _ref6$size = _ref6.size,
size = _ref6$size === void 0 ? 20 : _ref6$size,
bg = _ref6.bg,
initials = _ref6.initials,
alt = _ref6.alt,
rest = _objectWithoutProperties(_ref6, _excluded);
return (
/*#__PURE__*/
// `...rest` carries the props AvatarGroup and its Tooltip inject via
// cloneElement — `style` (overlap margin + paper ring) and the hover handlers
// (`onMouseOver` / `onMouseLeave`) — plus the forwarded `ref`, all of which
// must reach the DOM node for the tooltip to open.
_react.default.createElement(_RoundAvatar.RoundAvatar, _extends({
ref: ref,
$bg: bg,
$size: size,
$bordered: false
}, rest), initials)
);
});
MockAvatar.displayName = "MockAvatar";
/* The app removes AvatarGroup's default padding with `tw-p-0`; the mock does
the same through a styled wrapper (`tw-` classes don't run in Storybook). */
var StyledAvatarGroup = (0, _styledComponents.default)(_AvatarGroup.AvatarGroup).withConfig({
displayName: "SourceCodeSection__StyledAvatarGroup",
componentId: "sc-rvqbh5-4"
})(["&&{padding:0;}"]);
var ContributorAvatars = function ContributorAvatars(_ref7) {
var contributors = _ref7.contributors;
return /*#__PURE__*/_react.default.createElement(StyledAvatarGroup, {
limit: 4,
size: 20,
hasTooltip: true
}, contributors.map(function (c) {
var _CONTRIBUTOR_NAMES$c$;
return /*#__PURE__*/_react.default.createElement(MockAvatar, {
key: c.initials,
bg: c.bg,
initials: c.initials,
alt: (_CONTRIBUTOR_NAMES$c$ = CONTRIBUTOR_NAMES[c.initials]) !== null && _CONTRIBUTOR_NAMES$c$ !== void 0 ? _CONTRIBUTOR_NAMES$c$ : c.initials
});
}));
};
var IssueRow = exports.IssueRow = function IssueRow(_ref8) {
var issue = _ref8.issue;
var closed = issue.state === "closed";
return /*#__PURE__*/_react.default.createElement("div", {
className: "sc-row"
}, /*#__PURE__*/_react.default.createElement("div", {
className: "sc-main"
}, /*#__PURE__*/_react.default.createElement("div", {
className: "sc-name"
}, /*#__PURE__*/_react.default.createElement("span", {
className: "sc-lead",
style: {
color: closed ? "var(--color-primary)" : undefined
}
}, /*#__PURE__*/_react.default.createElement(IssueStateIcon, {
closed: closed
})), /*#__PURE__*/_react.default.createElement(_Typography.Body1, {
weight: "medium",
className: "sc-title"
}, /*#__PURE__*/_react.default.createElement(TitleLink, {
href: issueUrl(issue),
target: "_blank",
rel: "noopener noreferrer"
}, issue.title)), closed && /*#__PURE__*/_react.default.createElement(StatusChip, {
label: "Closed",
tone: "done",
glyph: /*#__PURE__*/_react.default.createElement(IssueStateIcon, {
closed: true,
size: 12
})
})), /*#__PURE__*/_react.default.createElement("div", {
className: "sc-sigs"
}, /*#__PURE__*/_react.default.createElement(_Tooltip.Tooltip, {
title: "Repository: ".concat(issue.repoFull)
}, /*#__PURE__*/_react.default.createElement("span", {
className: "sc-sig"
}, /*#__PURE__*/_react.default.createElement(_Icons.GitRepositoryIcon, {
width: 14,
height: 14
}), issue.repo)), /*#__PURE__*/_react.default.createElement("span", {
className: "sc-muted"
}, issue.updatedLabel))));
};
var CodeStatusChip = function CodeStatusChip(_ref9) {
var entry = _ref9.entry;
if (entry.status === "merged") {
return /*#__PURE__*/_react.default.createElement(StatusChip, {
label: "Merged",
tone: "done",
glyph: /*#__PURE__*/_react.default.createElement(_Icons.GitPullRequestIcon, {
width: 12,
height: 12,
fill: "var(--color-primary)"
})
});
}
if (entry.status === "deleted") {
return /*#__PURE__*/_react.default.createElement(StatusChip, {
label: "Deleted",
tone: "gone",
glyph: /*#__PURE__*/_react.default.createElement(_Icons.TrashIcon, {
width: 12,
height: 12,
fill: "var(--color-theme-900)"
})
});
}
if (entry.status === "closed") {
return /*#__PURE__*/_react.default.createElement(StatusChip, {
label: "Closed",
tone: "gone"
});
}
// Open branches / PRs show no status label.
return null;
};
var CodeRow = exports.CodeRow = function CodeRow(_ref0) {
var entry = _ref0.entry,
onOpenHistory = _ref0.onOpenHistory;
var deleted = entry.status === "deleted";
// A closed-without-merge PR is still a live link, but its name is struck
// through to signal the dead-end; the strike lifts on hover so it reads as a
// normal PR link.
var closedPr = entry.kind === "pr" && entry.status === "closed";
return /*#__PURE__*/_react.default.createElement("div", {
className: "sc-row"
}, /*#__PURE__*/_react.default.createElement("div", {
className: "sc-main"
}, /*#__PURE__*/_react.default.createElement("div", {
className: "sc-name"
}, /*#__PURE__*/_react.default.createElement("span", {
className: "sc-lead"
}, entry.kind === "pr" ? /*#__PURE__*/_react.default.createElement(_Icons.GitPullRequestIcon, {
width: 16,
height: 16
}) : /*#__PURE__*/_react.default.createElement(_Icons.GitBranchIcon, {
width: 16,
height: 16
})), deleted ? /*#__PURE__*/_react.default.createElement(_Typography.Body1, {
weight: "medium",
className: "sc-title strike"
}, entry.title) : /*#__PURE__*/_react.default.createElement(_Typography.Body1, {
weight: "medium",
className: closedPr ? "sc-title strike-link" : "sc-title"
}, /*#__PURE__*/_react.default.createElement(TitleLink, {
href: codeUrl(entry),
target: "_blank",
rel: "noopener noreferrer"
}, entry.title)), /*#__PURE__*/_react.default.createElement(CodeStatusChip, {
entry: entry
}), entry.kind === "pr" && entry.status === "open" && entry.closing && /*#__PURE__*/_react.default.createElement(_Tooltip.Tooltip, {
title: "Marks the task as completed when this pull request is merged."
}, /*#__PURE__*/_react.default.createElement("span", {
className: "sc-closing"
}, /*#__PURE__*/_react.default.createElement(StatusChip, {
label: "Closing",
tone: "info",
glyph: /*#__PURE__*/_react.default.createElement(_Icons.CheckIcon, {
width: 12,
height: 12,
fill: _utils.colors.blueSky.lighter
})
})))), /*#__PURE__*/_react.default.createElement("div", {
className: "sc-sigs"
}, /*#__PURE__*/_react.default.createElement(_Tooltip.Tooltip, {
title: "Repository: ".concat(entry.repoFull)
}, /*#__PURE__*/_react.default.createElement("span", {
className: "sc-sig"
}, /*#__PURE__*/_react.default.createElement(_Icons.GitRepositoryIcon, {
width: 14,
height: 14
}), entry.repo)), /*#__PURE__*/_react.default.createElement(ContributorAvatars, {
contributors: entry.contributors
}), /*#__PURE__*/_react.default.createElement(_Tooltip.Tooltip, {
title: entry.commits.tip
}, /*#__PURE__*/_react.default.createElement(_Typography.Caption1, {
color: "tertiary",
className: "sc-sig"
}, /*#__PURE__*/_react.default.createElement(_Icons.GitCommitIcon, {
width: 14,
height: 14
}), entry.commits.value)), /*#__PURE__*/_react.default.createElement(_Tooltip.Tooltip, {
title: "Head commit: ".concat(entry.headSha)
}, /*#__PURE__*/_react.default.createElement(_Typography.Caption1, {
color: "tertiary",
className: "sc-sig sc-sha"
}, entry.headSha.slice(0, 8))), entry.diff && /*#__PURE__*/_react.default.createElement(_Tooltip.Tooltip, {
title: entry.diff.tip
}, /*#__PURE__*/_react.default.createElement("span", {
className: "sc-sig sc-diff"
}, /*#__PURE__*/_react.default.createElement(_Typography.Caption1, {
color: "success"
}, "+", entry.diff.add), /*#__PURE__*/_react.default.createElement(_Typography.Caption1, {
color: "alert"
}, "\u2212", entry.diff.del))), entry.comments && /*#__PURE__*/_react.default.createElement(_Tooltip.Tooltip, {
title: entry.comments.tip
}, /*#__PURE__*/_react.default.createElement(_Typography.Caption1, {
color: "tertiary",
className: "sc-sig"
}, /*#__PURE__*/_react.default.createElement(_Icons.MessageSmallIcon, null), entry.comments.value)), /*#__PURE__*/_react.default.createElement("span", {
className: "sc-muted"
}, entry.updatedLabel))), /*#__PURE__*/_react.default.createElement(Spine, {
items: entry.stages,
onClick: onOpenHistory
}));
};
var CompletedHeader = exports.CompletedHeader = function CompletedHeader(_ref1) {
var expanded = _ref1.expanded,
count = _ref1.count,
onToggle = _ref1.onToggle;
return /*#__PURE__*/_react.default.createElement("div", {
className: "sc-completed-row"
}, /*#__PURE__*/_react.default.createElement(_Button.Button, {
type: "button",
variant: "text colored",
onClick: onToggle,
"aria-expanded": expanded,
style: {
marginLeft: -8
}
}, expanded ? "Hide completed elements" : "Show ".concat(count, " more completed elements")));
};
var SourceCodeSection = exports.SourceCodeSection = function SourceCodeSection(_ref10) {
var _ref10$variant = _ref10.variant,
variant = _ref10$variant === void 0 ? "mix" : _ref10$variant,
issues = _ref10.issues,
code = _ref10.code,
_ref10$showHeader = _ref10.showHeader,
showHeader = _ref10$showHeader === void 0 ? true : _ref10$showHeader,
_ref10$showLink = _ref10.showLink,
showLink = _ref10$showLink === void 0 ? true : _ref10$showLink,
_ref10$flush = _ref10.flush,
flush = _ref10$flush === void 0 ? false : _ref10$flush;
var _useState = (0, _react.useState)(null),
_useState2 = _slicedToArray(_useState, 2),
openEntry = _useState2[0],
setOpenEntry = _useState2[1];
var _useState3 = (0, _react.useState)(false),
_useState4 = _slicedToArray(_useState3, 2),
completedExpanded = _useState4[0],
setCompletedExpanded = _useState4[1];
var _useState5 = (0, _react.useState)(false),
_useState6 = _slicedToArray(_useState5, 2),
linkOpen = _useState6[0],
setLinkOpen = _useState6[1];
var issuesData = issues !== null && issues !== void 0 ? issues : ISSUES;
var codeData = code !== null && code !== void 0 ? code : CODE_ENTRIES;
var openIssues = issuesData.filter(function (i) {
return !issueCompleted(i);
}).sort(byRecency);
var openCode = codeData.filter(function (e) {
return !codeCompleted(e);
}).sort(byRecency);
var completed = [...issuesData.filter(issueCompleted).map(function (issue) {
return {
key: issue.ref,
updatedMinsAgo: issue.updatedMinsAgo,
node: /*#__PURE__*/_react.default.createElement(IssueRow, {
issue: issue
})
};
}), ...codeData.filter(codeCompleted).map(function (entry) {
return {
key: "".concat(entry.repo, "-").concat(entry.title),
updatedMinsAgo: entry.updatedMinsAgo,
node: /*#__PURE__*/_react.default.createElement(CodeRow, {
entry: entry,
onOpenHistory: function onOpenHistory() {
return setOpenEntry(entry);
}
})
};
})].sort(byRecency);
var showOpen = variant === "mix" || variant === "open";
var showCompleted = variant === "mix" || variant === "completed";
// In the "completed" variant there is no collapsible header and everything is
// shown; in "mix" the section is collapsed by default.
var completedVisible = variant === "completed" ? true : completedExpanded;
return /*#__PURE__*/_react.default.createElement(StyledSourceCode, {
$flush: flush
}, showHeader && /*#__PURE__*/_react.default.createElement("div", {
className: "sc-header"
}, /*#__PURE__*/_react.default.createElement(_Typography.Body1, {
weight: "bold"
}, "Source Code"), /*#__PURE__*/_react.default.createElement(_LinkingCommandsButton.LinkingCommandsButton, null)), showOpen && openIssues.map(function (issue) {
return /*#__PURE__*/_react.default.createElement("div", {
className: "sc-item",
key: issue.ref
}, /*#__PURE__*/_react.default.createElement(IssueRow, {
issue: issue
}));
}), showOpen && openCode.map(function (entry) {
return /*#__PURE__*/_react.default.createElement("div", {
className: "sc-item",
key: "".concat(entry.repo, "-").concat(entry.title)
}, /*#__PURE__*/_react.default.createElement(CodeRow, {
entry: entry,
onOpenHistory: function onOpenHistory() {
return setOpenEntry(entry);
}
}));
}), showCompleted && completedVisible && completed.map(function (c) {
return /*#__PURE__*/_react.default.createElement("div", {
className: "sc-item",
key: c.key
}, c.node);
}), showCompleted && completed.length > 0 && variant === "mix" && /*#__PURE__*/_react.default.createElement(CompletedHeader, {
expanded: completedExpanded,
count: completed.length,
onToggle: function onToggle() {
return setCompletedExpanded(function (v) {
return !v;
});
}
}), showLink && /*#__PURE__*/_react.default.createElement("div", {
className: "sc-add"
}, /*#__PURE__*/_react.default.createElement(_AddToListButton.AddToListButton, {
text: "Link Branch or Pull Request",
style: {
marginLeft: -4
},
onClick: function onClick() {
return setLinkOpen(true);
}
})), /*#__PURE__*/_react.default.createElement(HistoryDialog, {
entry: openEntry,
onClose: function onClose() {
return setOpenEntry(null);
}
}), /*#__PURE__*/_react.default.createElement(_LinkBranchOrPullRequestDialog.LinkBranchOrPullRequestDialog, {
open: linkOpen,
onClose: function onClose() {
return setLinkOpen(false);
}
}));
};
//# sourceMappingURL=SourceCodeSection.js.map