@@ -46,3 +46,7 @@ export function activateGithubProvisioning(): Promise<void> { | |||
export function deactivateGithubProvisioning(): Promise<void> { | |||
return post('/api/github_provisioning/disable').catch(throwGlobalError); | |||
} | |||
export function syncNowGithubProvisioning(): Promise<void> { | |||
return post('/api/github_provisioning/sync').catch(throwGlobalError); | |||
} |
@@ -19,18 +19,15 @@ | |||
*/ | |||
import { formatDistance } from 'date-fns'; | |||
import * as React from 'react'; | |||
import { useContext } from 'react'; | |||
import { FormattedMessage } from 'react-intl'; | |||
import Link from '../../components/common/Link'; | |||
import CheckIcon from '../../components/icons/CheckIcon'; | |||
import { Alert } from '../../components/ui/Alert'; | |||
import { translate, translateWithParameters } from '../../helpers/l10n'; | |||
import { useSyncStatusQuery } from '../../queries/github-sync'; | |||
import { Feature } from '../../types/features'; | |||
import { GithubStatusEnabled } from '../../types/provisioning'; | |||
import { TaskStatuses } from '../../types/tasks'; | |||
import './SystemAnnouncement.css'; | |||
import { AvailableFeaturesContext } from './available-features/AvailableFeaturesContext'; | |||
interface LastSyncProps { | |||
short?: boolean; | |||
@@ -100,10 +97,7 @@ function LastSyncAlert({ info, short }: LastSyncProps) { | |||
} | |||
function GitHubSynchronisationWarning({ short }: GitHubSynchronisationWarningProps) { | |||
const hasGithubProvisioning = useContext(AvailableFeaturesContext).includes( | |||
Feature.GithubProvisioning | |||
); | |||
const { data } = useSyncStatusQuery({ enabled: hasGithubProvisioning }); | |||
const { data } = useSyncStatusQuery(); | |||
if (!data) { | |||
return null; | |||
@@ -113,7 +107,7 @@ function GitHubSynchronisationWarning({ short }: GitHubSynchronisationWarningPro | |||
<> | |||
{!short && data?.nextSync && ( | |||
<> | |||
<Alert variant="loading"> | |||
<Alert variant="loading" className="spacer-bottom"> | |||
{translate( | |||
data.nextSync.status === TaskStatuses.Pending | |||
? 'settings.authentication.github.synchronization_pending' |
@@ -30,6 +30,7 @@ import DeleteIcon from '../../../../components/icons/DeleteIcon'; | |||
import EditIcon from '../../../../components/icons/EditIcon'; | |||
import { Alert } from '../../../../components/ui/Alert'; | |||
import { translate, translateWithParameters } from '../../../../helpers/l10n'; | |||
import { useSyncNow } from '../../../../queries/github-sync'; | |||
import { AlmKeys } from '../../../../types/alm-settings'; | |||
import { ExtendedSettingDefinition } from '../../../../types/settings'; | |||
import { DOCUMENTATION_LINK_SUFFIXES } from './Authentication'; | |||
@@ -78,6 +79,7 @@ export default function GithubAuthenticationTab(props: GithubAuthenticationProps | |||
} = useGithubConfiguration(definitions); | |||
const hasDifferentProvider = data?.provider !== undefined && data.provider !== Provider.Github; | |||
const { canSyncNow, synchronizeNow } = useSyncNow(); | |||
const handleCreateConfiguration = () => { | |||
setShowEditModal(true); | |||
@@ -220,6 +222,15 @@ export default function GithubAuthenticationTab(props: GithubAuthenticationProps | |||
/> | |||
</p> | |||
{githubProvisioningStatus && <GitHubSynchronisationWarning />} | |||
<div className="sw-flex sw-flex-1 sw-items-end"> | |||
<Button | |||
className="spacer-top width-30" | |||
onClick={synchronizeNow} | |||
disabled={!canSyncNow} | |||
> | |||
{translate('settings.authentication.github.synchronize_now')} | |||
</Button> | |||
</div> | |||
</> | |||
) : ( | |||
<p> |
@@ -52,11 +52,7 @@ export function useScimStatusQuery() { | |||
} | |||
export function useGithubStatusQuery() { | |||
const hasGithubProvisioning = useContext(AvailableFeaturesContext).includes( | |||
Feature.GithubProvisioning | |||
); | |||
const res = useSyncStatusQuery({ enabled: hasGithubProvisioning }); | |||
const res = useSyncStatusQuery(); | |||
return { ...res, data: res.data?.enabled }; | |||
} |
@@ -17,9 +17,33 @@ | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
import { useQuery } from '@tanstack/react-query'; | |||
import { fetchGithubProvisioningStatus } from '../api/provisioning'; | |||
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'; | |||
import { useContext } from 'react'; | |||
import { fetchGithubProvisioningStatus, syncNowGithubProvisioning } from '../api/provisioning'; | |||
import { AvailableFeaturesContext } from '../app/components/available-features/AvailableFeaturesContext'; | |||
import { Feature } from '../types/features'; | |||
export const useSyncStatusQuery = ({ enabled }: { enabled?: boolean }) => { | |||
return useQuery(['github_sync', 'status'], fetchGithubProvisioningStatus, { enabled }); | |||
}; | |||
export function useSyncStatusQuery() { | |||
const hasGithubProvisioning = useContext(AvailableFeaturesContext).includes( | |||
Feature.GithubProvisioning | |||
); | |||
return useQuery(['github_sync', 'status'], fetchGithubProvisioningStatus, { | |||
enabled: hasGithubProvisioning, | |||
refetchInterval: 10_000, | |||
}); | |||
} | |||
export function useSyncNow() { | |||
const queryClient = useQueryClient(); | |||
const { data } = useSyncStatusQuery(); | |||
const mutation = useMutation(syncNowGithubProvisioning, { | |||
onSuccess: () => { | |||
queryClient.invalidateQueries(['github_sync']); | |||
}, | |||
}); | |||
return { | |||
synchronizeNow: mutation.mutate, | |||
canSyncNow: data && data.enabled && !data.nextSync && !mutation.isLoading, | |||
}; | |||
} |
@@ -1386,6 +1386,7 @@ settings.authentication.github.form.provisioning_with_github=Automatic user and | |||
settings.authentication.github.form.provisioning_with_github.description=Users and groups are automatically provisioned from your GitHub organizations. Once activated, managed users and groups can only be modified from your GitHub organizations/teams. Existing local users and groups will be kept. | |||
settings.authentication.github.form.provisioning_with_github.description.doc=For more details, see {documentation}. | |||
settings.authentication.github.form.provisioning.disabled=Your current edition does not support provisioning with GitHub. See the {documentation} for more information. | |||
settings.authentication.github.synchronize_now=Synchronize now | |||
settings.authentication.github.synchronization_in_progress=Synchronization is in progress. | |||
settings.authentication.github.synchronization_pending=Synchronization is scheduled. | |||
settings.authentication.github.synchronization_successful=Last synchronization was done {0} ago. |