1616 * limitations under the License.
1717 */
1818
19+ import { skipToken } from "@reduxjs/toolkit/query" ;
1920import cx from "classnames" ;
2021import { useCallback , useContext , useEffect , useMemo , useState } from "react" ;
2122import {
@@ -51,24 +52,33 @@ import { ErrorAlert, InfoAlert, WarnAlert } from "~/components/Alert";
5152import { CommandCopy } from "~/components/commandCopy/CommandCopy" ;
5253import ExternalLink from "~/components/ExternalLink" ;
5354import RenkuBadge from "~/components/renkuBadge/RenkuBadge" ;
55+ import {
56+ useGetOauth2ProvidersQuery ,
57+ type ConnectionStatus ,
58+ } from "~/features/connectedServices/api/connectedServices.api" ;
5459import {
5560 SEARCH_PARAM_ACTION_REQUIRED ,
5661 SEARCH_PARAM_PROVIDER ,
5762 SEARCH_PARAM_SOURCE ,
5863} from "~/features/connectedServices/connectedServices.constants" ;
5964import RepositoryGitLabWarnBadge from "~/features/legacy/RepositoryGitLabWarnBadge" ;
60- import { useGetRepositoryQuery } from "~/features/repositories/api/repositories.api" ;
65+ import {
66+ repositoriesApi ,
67+ useGetRepositoryQuery ,
68+ } from "~/features/repositories/api/repositories.api" ;
6169import { useGetUserQueryState } from "~/features/usersV2/api/users.api" ;
6270import { ABSOLUTE_ROUTES } from "~/routing/routes.constants" ;
6371import AppContext from "~/utils/context/appContext" ;
6472import { DEFAULT_APP_PARAMS } from "~/utils/context/appParams.constants" ;
73+ import useAppDispatch from "~/utils/customHooks/useAppDispatch.hook" ;
6574import { ButtonWithMenuV2 } from "../../../../components/buttons/Button" ;
6675import RtkOrDataServicesError from "../../../../components/errors/RtkOrDataServicesError" ;
6776import { Loader } from "../../../../components/Loader" ;
6877import PermissionsGuard from "../../../permissionsV2/PermissionsGuard" ;
6978import { Project } from "../../../projectsV2/api/projectV2.api" ;
7079import { usePatchProjectsByProjectIdMutation } from "../../../projectsV2/api/projectV2.enhanced-api" ;
7180import useProjectPermissions from "../../utils/useProjectPermissions.hook" ;
81+ import { ConnectButton } from "./../../../connectedServices/ConnectedServicesPage" ;
7282import { SshRepositoryUrlWarning } from "./AddCodeRepositoryModal" ;
7383import {
7484 getRepositoryName ,
@@ -658,6 +668,7 @@ function RepositoryView({
658668 < RepositoryCallToActionAlert
659669 hasWriteAccess = { projectPermissions ?. write }
660670 repositoryUrl = { repositoryUrl }
671+ project = { project }
661672 />
662673 </ div >
663674
@@ -697,7 +708,7 @@ function RepositoryView({
697708 (
698709 < Link
699710 to = { {
700- pathname : ABSOLUTE_ROUTES . v2 . integrations ,
711+ pathname : ABSOLUTE_ROUTES . v2 . integrations . root ,
701712 search,
702713 } }
703714 >
@@ -730,11 +741,14 @@ function LogInWarning() {
730741interface RepositoryCallToActionAlertProps {
731742 hasWriteAccess : boolean ;
732743 repositoryUrl : string ;
744+ project : Project ;
733745}
734746export function RepositoryCallToActionAlert ( {
735747 hasWriteAccess,
736748 repositoryUrl,
749+ project,
737750} : RepositoryCallToActionAlertProps ) {
751+ const dispatch = useAppDispatch ( ) ;
738752 const { pathname, hash } = useLocation ( ) ;
739753 const { params } = useContext ( AppContext ) ;
740754 const renkuContactEmail =
@@ -748,12 +762,24 @@ export function RepositoryCallToActionAlert({
748762 return userInfo && ! userInfo ?. isLoggedIn ;
749763 } , [ userInfo ] ) ;
750764
751- const search = useMemo ( ( ) => {
752- return `?${ new URLSearchParams ( {
753- [ SEARCH_PARAM_PROVIDER ] : data ?. provider ?. id ?? "" ,
754- [ SEARCH_PARAM_SOURCE ] : `${ pathname } ${ hash } ` ,
755- } ) . toString ( ) } `;
756- } , [ data , pathname , hash ] ) ;
765+ const { data : oauthProviders } = useGetOauth2ProvidersQuery (
766+ anonymousUser ? skipToken : undefined
767+ ) ;
768+ const oauthProvider = useMemo (
769+ ( ) => oauthProviders ?. find ( ( p ) => p . id === data ?. provider ?. id ) ?? undefined ,
770+ [ data ?. provider ?. id , oauthProviders ]
771+ ) ;
772+
773+ const onRepositoryOAuthConnected = useCallback ( ( ) => {
774+ project . repositories ?. map ( ( repoUrl ) => {
775+ dispatch (
776+ repositoriesApi . util . invalidateTags ( [
777+ { type : "Repository" , id : repoUrl } ,
778+ ] )
779+ ) ;
780+ } ) ;
781+ } , [ dispatch , project ] ) ;
782+
757783 const searchActionRequired = useMemo ( ( ) => {
758784 return `?${ new URLSearchParams ( {
759785 [ SEARCH_PARAM_PROVIDER ] : data ?. provider ?. id ?? "" ,
@@ -777,29 +803,35 @@ export function RepositoryCallToActionAlert({
777803 { data ?. provider ?. id ? (
778804 < >
779805 < p className = "mb-2" >
780- Either the repository does not exist, or you do not have access to
781- it.
806+ The repository is not accessible and your connection to{ " " }
807+ < span className = "fst-italic" > { data . provider . name } </ span > is
808+ invalid.
782809 </ p >
783810 { anonymousUser ? (
784811 < LogInWarning />
785812 ) : (
786813 < >
787- < p className = "mb-2" >
788- If you think you should have access, check your integration{ " " }
789- < span className = "fst-italic" > { data . provider . name } </ span > .
790- </ p >
814+ < p className = "mb-2" > You can try to refresh it.</ p >
815+ { oauthProvider && (
816+ < ConnectButton
817+ className = "btn-sm"
818+ connectionStatus = {
819+ data . connection ?. status as ConnectionStatus | undefined
820+ }
821+ includeSource
822+ onConnected = { onRepositoryOAuthConnected }
823+ provider = { oauthProvider }
824+ withIcon
825+ />
826+ ) }
791827 < Link
792- className = { cx ( "btn" , "btn-primary" , "btn-sm" ) }
828+ className = { cx ( "btn" , "btn-outline- primary" , "btn-sm" , "ms-2 ") }
793829 to = { {
794- pathname : ABSOLUTE_ROUTES . v2 . integrations ,
795- search :
796- data ?. connection ?. status === "connected"
797- ? search
798- : searchActionRequired ,
830+ pathname : ABSOLUTE_ROUTES . v2 . integrations . root ,
831+ search : searchActionRequired ,
799832 } }
800833 >
801- < Plugin className = { cx ( "bi" , "me-1" ) } />
802- View integration
834+ Check integration
803835 </ Link >
804836 </ >
805837 ) }
@@ -816,7 +848,7 @@ export function RepositoryCallToActionAlert({
816848 currently supported{ " " }
817849 < Link
818850 to = { {
819- pathname : ABSOLUTE_ROUTES . v2 . integrations ,
851+ pathname : ABSOLUTE_ROUTES . v2 . integrations . root ,
820852 } }
821853 >
822854 < Plugin className = { cx ( "bi" , "me-1" ) } />
@@ -892,19 +924,30 @@ export function RepositoryCallToActionAlert({
892924 data-cy = "code-repository-alert"
893925 >
894926 < p className = "mb-2" >
895- You can log in through the integration { " " }
927+ You can connect to { " " }
896928 < span className = "fst-italic" > { data . provider . name } </ span > to enable
897929 pushing to repositories for which you have permissions.
898930 </ p >
931+ { oauthProvider && (
932+ < ConnectButton
933+ className = "btn-sm"
934+ connectionStatus = {
935+ data . connection ?. status as ConnectionStatus | undefined
936+ }
937+ includeSource
938+ onConnected = { onRepositoryOAuthConnected }
939+ provider = { oauthProvider }
940+ withIcon
941+ />
942+ ) }
899943 < Link
900- className = { cx ( "btn" , "btn-primary" , "btn-sm" ) }
944+ className = { cx ( "btn" , "btn-outline- primary" , "btn-sm" , "ms-2 ") }
901945 to = { {
902- pathname : ABSOLUTE_ROUTES . v2 . integrations ,
946+ pathname : ABSOLUTE_ROUTES . v2 . integrations . root ,
903947 search : searchActionRequired ,
904948 } }
905949 >
906- < Plugin className = { cx ( "bi" , "me-1" ) } />
907- View integration
950+ Check integration
908951 </ Link >
909952 </ WarnAlert >
910953 ) ;
@@ -931,17 +974,28 @@ export function RepositoryCallToActionAlert({
931974 { anonymousUser ? (
932975 < LogInWarning />
933976 ) : (
934- < Link
935- className = { cx ( "btn" , "btn-primary" , "btn-sm" ) }
936- to = { {
937- pathname : ABSOLUTE_ROUTES . v2 . integrations ,
938- search : searchActionRequired ,
939- } }
940- >
941- < Plugin className = { cx ( "bi" , "me-1" ) } />
942- View integration
943- </ Link >
977+ oauthProvider && (
978+ < ConnectButton
979+ className = "btn-sm"
980+ connectionStatus = {
981+ data . connection ?. status as ConnectionStatus | undefined
982+ }
983+ includeSource
984+ onConnected = { onRepositoryOAuthConnected }
985+ provider = { oauthProvider }
986+ withIcon
987+ />
988+ )
944989 ) }
990+ < Link
991+ className = { cx ( "btn" , "btn-outline-primary" , "btn-sm" , "ms-2" ) }
992+ to = { {
993+ pathname : ABSOLUTE_ROUTES . v2 . integrations . root ,
994+ search : searchActionRequired ,
995+ } }
996+ >
997+ Check integration
998+ </ Link >
945999 </ InfoAlert >
9461000 ) ;
9471001 }
0 commit comments