UNPKG

@activecollab/components

Version:

ActiveCollab Components

290 lines (277 loc) 13.3 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.serviceLabel = exports.connectionIcon = exports.buildRepoOptions = exports.RepositorySelect = exports.PROJECT_REPOSITORIES = exports.ConnectRepositoryDialog = exports.CONNECTIONS = exports.CONNECTABLE_REPOSITORIES = void 0; var _react = _interopRequireWildcard(require("react")); var _styledComponents = _interopRequireWildcard(require("styled-components")); var _Button = require("../../components/Button"); var _Checkbox = require("../../components/Checkbox"); var _Dialog = require("../../components/Dialog"); var _Icons = require("../../components/Icons"); var _Label = require("../../components/Label"); var _Select = require("../../components/Select"); var _SelectTrigger = require("../../components/SelectTrigger"); var _Typography = require("../../components/Typography"); 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; } /** * "Connect Repository" — the project-side counterpart to the "Connect Project" * dialog on the Repositories page (Apps & Integrations). Same operation from * the other end: pick a repository, choose which features to enable, and make * the connection. Built as a shared component because more than one story links * a repository this way. * * Also exports `RepositorySelect`, the grouped repository picker (repositories * grouped under their connection name, everything sorted by name, filterable * via the built-in search) reused wherever a repository is chosen. */ var SANS = '-apple-system, BlinkMacSystemFont, "Roboto", "Helvetica Neue", Arial, sans-serif'; /* ---- Data model + mock data ----------------------------------------- */ /** Human-readable provider label used in the group header "name (type)". */ var serviceLabel = exports.serviceLabel = function serviceLabel(service) { return service === "github" ? "GitHub" : "GitLab"; }; /** Provider glyph for a connection: GitHub / GitLab, Git for anything else. */ var connectionIcon = exports.connectionIcon = function connectionIcon(service) { if (service === "github") { return /*#__PURE__*/_react.default.createElement(_Icons.GitHubIcon, null); } if (service === "gitlab") { return /*#__PURE__*/_react.default.createElement(_Icons.GitLabIcon, null); } return /*#__PURE__*/_react.default.createElement(_Icons.GitIcon, null); }; var CONNECTIONS = exports.CONNECTIONS = [{ id: "gh-ac", name: "ActiveCollab", service: "github" }, { id: "gl-ops", name: "a51-ops", service: "gitlab" }]; /** Repositories already connected to the project (shown in link pickers). */ var PROJECT_REPOSITORIES = exports.PROJECT_REPOSITORIES = [{ id: "backend", name: "activecollab/backend", connectionId: "gh-ac" }, { id: "frontend", name: "activecollab/frontend", connectionId: "gh-ac" }, { id: "infra", name: "activecollab/infrastructure", connectionId: "gl-ops" }]; /** Repositories available to connect (not yet linked to the project). */ var CONNECTABLE_REPOSITORIES = exports.CONNECTABLE_REPOSITORIES = [{ id: "mobile", name: "activecollab/mobile", connectionId: "gh-ac" }, { id: "design-system", name: "activecollab/design-system", connectionId: "gh-ac" }, { id: "deploy-scripts", name: "a51-ops/deploy-scripts", connectionId: "gl-ops" }, { id: "runners", name: "a51-ops/ci-runners", connectionId: "gl-ops" }]; /** * Build grouped Select options — groups and options both sorted by name. Each * repository option carries a leading provider icon (GitHub / GitLab / Git) via * the Select's `icon` slot; the group header is just the connection name, since * the icon now conveys the service (no "(GitHub)" / "(GitLab)" suffix). */ var buildRepoOptions = exports.buildRepoOptions = function buildRepoOptions(repositories, connections) { return [...connections].map(function (c) { return { id: c.id, name: c.name, options: repositories.filter(function (r) { return r.connectionId === c.id; }).sort(function (a, b) { return a.name.localeCompare(b.name); }).map(function (r) { return { id: r.id, name: r.name, icon: connectionIcon(c.service) }; }) }; }).filter(function (group) { return group.options.length > 0; }).sort(function (a, b) { return a.name.localeCompare(b.name); }); }; /* ---- RepositorySelect ------------------------------------------------ */ /** * The grouped repository menu renders through a portal, so the "match the * trigger width" override has to be global, scoped to this instance's class. */ var RepoMenuGlobalStyle = (0, _styledComponents.createGlobalStyle)([".c-select.", "{", "}"], function (p) { return p.$cls; }, function (p) { return p.$w ? "width: ".concat(p.$w, "px !important; max-width: none !important;") : ""; }); var RepoSelectWrap = _styledComponents.default.div.withConfig({ displayName: "ConnectRepositoryDialog__RepoSelectWrap", componentId: "sc-7az7te-0" })(["font-family:", ";.repo-trigger{width:100%;max-width:none;}"], SANS); var RepositorySelect = exports.RepositorySelect = function RepositorySelect(_ref) { var _repositories$find$na, _repositories$find; var repositories = _ref.repositories, connections = _ref.connections, selected = _ref.selected, _onChange = _ref.onChange, invalid = _ref.invalid, _ref$placeholder = _ref.placeholder, placeholder = _ref$placeholder === void 0 ? "Choose repository" : _ref$placeholder, className = _ref.className; var wrapRef = (0, _react.useRef)(null); var _useState = (0, _react.useState)(), _useState2 = _slicedToArray(_useState, 2), menuWidth = _useState2[0], setMenuWidth = _useState2[1]; var _useState3 = (0, _react.useState)(function () { return "repo-select-menu-".concat(Math.random().toString(36).slice(2)); }), _useState4 = _slicedToArray(_useState3, 1), menuCls = _useState4[0]; var measure = (0, _react.useCallback)(function () { if (wrapRef.current) { setMenuWidth(wrapRef.current.offsetWidth); } }, []); (0, _react.useEffect)(function () { measure(); }, [measure]); var options = buildRepoOptions(repositories, connections); var selectedName = (_repositories$find$na = (_repositories$find = repositories.find(function (r) { return r.id === selected; })) === null || _repositories$find === void 0 ? void 0 : _repositories$find.name) !== null && _repositories$find$na !== void 0 ? _repositories$find$na : placeholder; return /*#__PURE__*/_react.default.createElement(RepoSelectWrap, { ref: wrapRef, className: className }, /*#__PURE__*/_react.default.createElement(RepoMenuGlobalStyle, { $cls: menuCls, $w: menuWidth }), /*#__PURE__*/_react.default.createElement(_Select.Select, { options: options, selected: selected === null ? undefined : selected, onChange: function onChange(v) { return _onChange(String(v)); }, placeholder: "Search repositories", selectClassName: menuCls, onSelectOpen: measure, forceCloseMenu: true, target: /*#__PURE__*/_react.default.createElement(_SelectTrigger.SelectTrigger, { className: "repo-trigger", invalid: invalid, typographyProps: selected === null ? { color: "tertiary" } : undefined }, selectedName) })); }; /* ---- ConnectRepositoryDialog ---------------------------------------- */ var StyledConnectBody = _styledComponents.default.div.withConfig({ displayName: "ConnectRepositoryDialog__StyledConnectBody", componentId: "sc-7az7te-1" })(["font-family:", ";.cr-field{margin-bottom:16px;}.cr-label{display:block;margin-bottom:6px;}.cr-check{display:flex;align-items:center;gap:8px;}.cr-check-hint{margin-top:6px;}"], SANS); var ConnectRepositoryDialog = exports.ConnectRepositoryDialog = function ConnectRepositoryDialog(_ref2) { var open = _ref2.open, onClose = _ref2.onClose, onConnect = _ref2.onConnect, _ref2$repositories = _ref2.repositories, repositories = _ref2$repositories === void 0 ? CONNECTABLE_REPOSITORIES : _ref2$repositories, _ref2$connections = _ref2.connections, connections = _ref2$connections === void 0 ? CONNECTIONS : _ref2$connections; var _useState5 = (0, _react.useState)(null), _useState6 = _slicedToArray(_useState5, 2), selected = _useState6[0], setSelected = _useState6[1]; var _useState7 = (0, _react.useState)(false), _useState8 = _slicedToArray(_useState7, 2), issueSync = _useState8[0], setIssueSync = _useState8[1]; var _useState9 = (0, _react.useState)(false), _useState0 = _slicedToArray(_useState9, 2), attempted = _useState0[0], setAttempted = _useState0[1]; // Reset the form each time the dialog opens. (0, _react.useEffect)(function () { if (open) { setSelected(null); setIssueSync(false); setAttempted(false); } }, [open]); var invalid = attempted && selected === null; var handleConnect = function handleConnect() { var repo = repositories.find(function (r) { return r.id === selected; }); if (!repo) { setAttempted(true); return; } onConnect(repo); onClose(); }; return /*#__PURE__*/_react.default.createElement(_Dialog.Dialog, { open: open, onClose: onClose, disableCloseOnEsc: true }, /*#__PURE__*/_react.default.createElement(_Dialog.Dialog.Title, null, "Connect Repository"), /*#__PURE__*/_react.default.createElement(_Dialog.Dialog.ContentDivider, null), /*#__PURE__*/_react.default.createElement(_Dialog.Dialog.Content, null, /*#__PURE__*/_react.default.createElement(StyledConnectBody, null, /*#__PURE__*/_react.default.createElement("div", { className: "cr-field" }, /*#__PURE__*/_react.default.createElement(_Label.Label, { size: "small", className: "cr-label", invalid: invalid }, "Repository"), /*#__PURE__*/_react.default.createElement(RepositorySelect, { repositories: repositories, connections: connections, selected: selected, onChange: setSelected, invalid: invalid })), /*#__PURE__*/_react.default.createElement("div", { className: "cr-check" }, /*#__PURE__*/_react.default.createElement(_Checkbox.Checkbox, { id: "cr-issue-sync", checked: issueSync, onChange: function onChange(e) { return setIssueSync(e.target.checked); } }), /*#__PURE__*/_react.default.createElement(_Label.Label, { htmlFor: "cr-issue-sync", weight: "regular" }, "Enable issue sync")), /*#__PURE__*/_react.default.createElement(_Typography.Body2, { className: "cr-check-hint", color: "tertiary" }, "Issues from this repository will create and update tasks in this project."))), /*#__PURE__*/_react.default.createElement(_Dialog.Dialog.ContentDivider, null), /*#__PURE__*/_react.default.createElement(_Dialog.Dialog.Actions, null, /*#__PURE__*/_react.default.createElement(_Button.Button, { variant: "primary", style: { marginRight: 12 }, onClick: handleConnect }, "Connect"), /*#__PURE__*/_react.default.createElement(_Button.Button, { variant: "secondary", onClick: onClose }, "Cancel"))); }; //# sourceMappingURL=ConnectRepositoryDialog.js.map