aboutsummaryrefslogtreecommitdiffstats
path: root/server/sonar-web/src/main/js/apps/projectsManagement/ProjectRowActions.tsx
blob: aedbd1db09a8257cd022d5a945e746f83d29e47b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
/*
 * SonarQube
 * Copyright (C) 2009-2024 SonarSource SA
 * mailto:info AT sonarsource DOT com
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 3 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */
import { ActionsDropdown, ItemButton, ItemLink, PopupZLevel, Spinner } from 'design-system';
import React, { useState } from 'react';
import { getComponentNavigation } from '../../api/navigation';
import { Project } from '../../api/project-management';
import { throwGlobalError } from '../../helpers/error';
import { translate, translateWithParameters } from '../../helpers/l10n';
import { getComponentPermissionsUrl } from '../../helpers/urls';
import { useGithubProvisioningEnabledQuery } from '../../queries/identity-provider/github';
import { LoggedInUser } from '../../types/users';
import ApplyTemplate from '../permissions/project/components/ApplyTemplate';
import RestoreAccessModal from './RestoreAccessModal';

export interface Props {
  currentUser: Pick<LoggedInUser, 'login' | 'local'>;
  project: Project;
}

export default function ProjectRowActions({ currentUser, project }: Props) {
  const [applyTemplateModal, setApplyTemplateModal] = useState(false);
  const [hasAccess, setHasAccess] = useState<boolean | undefined>(undefined);
  const [loading, setLoading] = useState(false);
  const [restoreAccessModal, setRestoreAccessModal] = useState(false);
  const { data: githubProvisioningEnabled } = useGithubProvisioningEnabledQuery();

  const fetchPermissions = async () => {
    setLoading(true);

    try {
      const { configuration } = await getComponentNavigation({ component: project.key });
      const hasAccess = Boolean(configuration?.showPermissions && configuration?.canBrowseProject);
      setHasAccess(hasAccess);
      setLoading(false);
    } catch (error) {
      throwGlobalError(error);
    } finally {
      setLoading(false);
    }
  };

  const handleDropdownOpen = () => {
    if (hasAccess === undefined && !loading) {
      fetchPermissions();
    }
  };

  const handleRestoreAccessDone = () => {
    setRestoreAccessModal(false);
    setHasAccess(true);
  };

  return (
    <>
      <ActionsDropdown
        id="project-management-action-dropdown"
        toggleClassName="it__user-actions-toggle"
        onOpen={handleDropdownOpen}
        allowResizing
        ariaLabel={translateWithParameters('projects_management.show_actions_for_x', project.name)}
        zLevel={PopupZLevel.Global}
      >
        <Spinner loading={loading} className="sw-flex sw-ml-3">
          <>
            {hasAccess === true && (
              <ItemLink to={getComponentPermissionsUrl(project.key)}>
                {translate(project.managed ? 'show_permissions' : 'edit_permissions')}
              </ItemLink>
            )}

            {hasAccess === false &&
              (!project.managed || currentUser.local || !githubProvisioningEnabled) && (
                <ItemButton
                  className="it__restore-access"
                  onClick={() => setRestoreAccessModal(true)}
                >
                  {translate('global_permissions.restore_access')}
                </ItemButton>
              )}
          </>
        </Spinner>

        {!project.managed && (
          <ItemButton className="it__apply-template" onClick={() => setApplyTemplateModal(true)}>
            {translate('projects_role.apply_template')}
          </ItemButton>
        )}
      </ActionsDropdown>

      {restoreAccessModal && (
        <RestoreAccessModal
          currentUser={currentUser}
          onClose={() => setRestoreAccessModal(false)}
          onRestoreAccess={handleRestoreAccessDone}
          project={project}
        />
      )}

      {applyTemplateModal && (
        <ApplyTemplate onClose={() => setApplyTemplateModal(false)} project={project} />
      )}
    </>
  );
}