3 * Copyright (C) 2009-2023 SonarSource SA
4 * mailto:info AT sonarsource DOT com
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 3 of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
24 LabelValueSelectOption,
29 } from 'design-system';
30 import * as React from 'react';
31 import { GroupBase, OptionProps, Options, SingleValue, components } from 'react-select';
32 import Avatar from '../../../components/ui/Avatar';
33 import { translate } from '../../../helpers/l10n';
34 import { Group as UserGroup, isUser } from '../../../types/quality-gates';
35 import { UserBase } from '../../../types/users';
37 export interface QualityGatePermissionsAddModalRendererProps {
41 resolve: (options: Options<LabelValueSelectOption<UserBase | UserGroup>>) => void,
43 onSelection: (selection: SingleValue<LabelValueSelectOption<UserBase | UserGroup>>) => void;
44 selection?: UserBase | UserGroup;
45 onSubmit: (event: React.SyntheticEvent<HTMLFormElement>) => void;
49 const FORM_ID = 'quality-gate-permissions-add-modal';
50 const USER_SELECT_INPUT_ID = 'quality-gate-permissions-add-modal-select-input';
52 export default function QualityGatePermissionsAddModalRenderer(
53 props: Readonly<QualityGatePermissionsAddModalRendererProps>,
55 const { selection, submitting } = props;
57 const renderedSelection = React.useMemo(() => {
58 return <OptionRenderer option={selection} small />;
63 onClose={props.onClose}
64 headerTitle={translate('quality_gates.permissions.grant')}
66 <form onSubmit={props.onSubmit} id={FORM_ID}>
68 label={translate('quality_gates.permissions.search')}
69 htmlFor={USER_SELECT_INPUT_ID}
73 controlAriaLabel={translate('quality_gates.permissions.search')}
74 inputId={USER_SELECT_INPUT_ID}
79 noOptionsMessage={() => translate('no_results')}
80 onChange={props.onSelection}
81 loadOptions={props.handleSearch}
82 getOptionValue={({ value }) => (isUser(value) ? value.login : value.name)}
83 controlLabel={renderedSelection}
92 <ButtonPrimary disabled={!selection || submitting} type="submit" form={FORM_ID}>
93 {translate('add_verb')}
96 secondaryButtonLabel={translate('cancel')}
101 function OptionRenderer({
105 option?: UserBase | UserGroup;
116 className={small ? 'sw-my-1/2' : ''}
119 size={small ? 'xs' : 'sm'}
121 <span className="sw-ml-2">
122 <strong className="sw-body-sm-highlight sw-mr-1">{option.name}</strong>
123 <Note>{option.login}</Note>
129 className={small ? 'sw-my-1/2' : ''}
132 size={small ? 'xs' : 'sm'}
134 <strong className="sw-body-sm-highlight sw-ml-2">{option.name}</strong>
142 Option extends LabelValueSelectOption<UserBase | UserGroup>,
143 IsMulti extends boolean = false,
144 Group extends GroupBase<Option> = GroupBase<Option>,
145 >(props: OptionProps<Option, IsMulti, Group>) {
151 <components.Option {...props}>
152 <div className="sw-flex sw-items-center">
153 <OptionRenderer option={value} />