diff --git a/apps/studio/src/modules/sync/components/tree-view-loading-skeleton.tsx b/apps/studio/src/modules/sync/components/tree-view-loading-skeleton.tsx
index b5e33efaaa..8d9929dcb3 100644
--- a/apps/studio/src/modules/sync/components/tree-view-loading-skeleton.tsx
+++ b/apps/studio/src/modules/sync/components/tree-view-loading-skeleton.tsx
@@ -1,15 +1,11 @@
-import { cx } from 'src/lib/cx';
-
export const TreeViewLoadingSkeleton = () => {
- const skeletonBg = 'animate-pulse bg-gradient-to-r from-[#F6F7F7] via-[#DCDCDE] to-[#F6F7F7]';
-
return (
{ [ 1, 2 ].map( ( key ) => (
) ) }
diff --git a/apps/studio/src/modules/sync/index.tsx b/apps/studio/src/modules/sync/index.tsx
index 8a88c56824..7a890037d7 100644
--- a/apps/studio/src/modules/sync/index.tsx
+++ b/apps/studio/src/modules/sync/index.tsx
@@ -132,10 +132,11 @@ export function ContentTabSync( { selectedSite }: { selectedSite: SiteDetails }
connectedSitesSelectors.selectSelectedRemoteSiteId
);
const { isAuthenticated, user } = useAuth();
- const { data: connectedSites = [] } = useGetConnectedSitesForLocalSiteQuery( {
- localSiteId: selectedSite.id,
- userId: user?.id,
- } );
+ const { data: connectedSites = [], isLoading: isLoadingConnectedSites } =
+ useGetConnectedSitesForLocalSiteQuery( {
+ localSiteId: selectedSite.id,
+ userId: user?.id,
+ } );
const [ connectSite ] = useConnectSiteMutation();
const [ disconnectSite ] = useDisconnectSiteMutation();
const { pushSite, pullSite } = useSyncSites();
@@ -214,7 +215,7 @@ export function ContentTabSync( { selectedSite }: { selectedSite: SiteDetails }
- ) : (
+ ) : isLoadingConnectedSites ? null : (
{
state.selectedRemoteSiteId = null;
},
+
+ addLoadingSiteId: ( state, action: PayloadAction< number > ) => {
+ if ( ! state.loadingSiteIds.includes( action.payload ) ) {
+ state.loadingSiteIds.push( action.payload );
+ }
+ },
+
+ removeLoadingSiteId: ( state, action: PayloadAction< number > ) => {
+ state.loadingSiteIds = state.loadingSiteIds.filter( ( id ) => id !== action.payload );
+ },
},
} );
@@ -50,6 +62,7 @@ export const connectedSitesSelectors = {
selectIsModalOpen: ( state: RootState ) => state.connectedSites.isModalOpen,
selectModalMode: ( state: RootState ) => state.connectedSites.modalMode,
selectSelectedRemoteSiteId: ( state: RootState ) => state.connectedSites.selectedRemoteSiteId,
+ selectLoadingSiteIds: ( state: RootState ) => state.connectedSites.loadingSiteIds,
};
export const connectedSitesApi = createApi( {
diff --git a/apps/studio/src/stores/sync/wpcom-sites.ts b/apps/studio/src/stores/sync/wpcom-sites.ts
index e794abbe49..9d1f634b56 100644
--- a/apps/studio/src/stores/sync/wpcom-sites.ts
+++ b/apps/studio/src/stores/sync/wpcom-sites.ts
@@ -117,11 +117,78 @@ function transformSitesResponse( sites: unknown[], connectedSiteIds?: number[] )
} );
}
+const SITE_FIELDS = [
+ 'name',
+ 'ID',
+ 'URL',
+ 'plan',
+ 'capabilities',
+ 'is_wpcom_atomic',
+ 'options',
+ 'jetpack',
+ 'is_deleted',
+ 'is_a8c',
+ 'hosting_provider_guess',
+ 'environment_type',
+].join( ',' );
+
export const wpcomSitesApi = createApi( {
reducerPath: 'wpcomSitesApi',
baseQuery: fetchBaseQuery(),
tagTypes: [ 'WpComSites' ],
endpoints: ( builder ) => ( {
+ getSingleWpComSite: builder.query< SyncSite, { siteId: number; userId?: number } >( {
+ queryFn: async ( { siteId } ) => {
+ const wpcomClient = getWpcomClient();
+ if ( ! wpcomClient ) {
+ return { error: { status: 401, data: 'Not authenticated' } };
+ }
+
+ try {
+ const response = await wpcomClient.req.get(
+ {
+ apiNamespace: 'rest/v1.1',
+ path: `/sites/${ siteId }`,
+ },
+ {
+ fields: SITE_FIELDS,
+ options: 'created_at,wpcom_staging_blog_ids',
+ }
+ );
+
+ const parsedSite = sitesEndpointSiteSchema.parse( response );
+
+ const allConnectedSites = await getIpcApi().getConnectedWpcomSites();
+
+ // Determine if staging by checking environment_type (can't access parent site's staging IDs without fetching /me/sites)
+ const isStaging =
+ parsedSite.environment_type === 'staging' ||
+ parsedSite.environment_type === 'development';
+
+ const syncSupport = getSyncSupport(
+ parsedSite,
+ allConnectedSites.map( ( { id } ) => id )
+ );
+
+ const syncSite = transformSingleSiteResponse( parsedSite, syncSupport, isStaging );
+
+ return { data: syncSite };
+ } catch ( error ) {
+ Sentry.captureException( error );
+ console.error( error );
+ return {
+ error: {
+ status: 500,
+ data: error,
+ },
+ };
+ }
+ },
+ providesTags: ( _result, _error, arg ) => [
+ { type: 'WpComSites', userId: arg.userId },
+ { type: 'WpComSites', id: arg.siteId },
+ ],
+ } ),
getWpComSites: builder.query< SyncSite[], { connectedSiteIds?: number[]; userId?: number } >( {
queryFn: async ( { connectedSiteIds } ) => {
const wpcomClient = getWpcomClient();
@@ -132,28 +199,13 @@ export const wpcomSitesApi = createApi( {
try {
const allConnectedSites = await getIpcApi().getConnectedWpcomSites();
- const fields = [
- 'name',
- 'ID',
- 'URL',
- 'plan',
- 'capabilities',
- 'is_wpcom_atomic',
- 'options',
- 'jetpack',
- 'is_deleted',
- 'is_a8c',
- 'hosting_provider_guess',
- 'environment_type',
- ].join( ',' );
-
const response = await wpcomClient.req.get(
{
apiNamespace: 'rest/v1.2',
path: `/me/sites`,
},
{
- fields,
+ fields: SITE_FIELDS,
filter: 'atomic,wpcom',
options: 'created_at,wpcom_staging_blog_ids',
site_activity: 'active',