Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 47 additions & 3 deletions client/dashboard/app/queries/domain-glue-records.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
import { queryOptions, mutationOptions } from '@tanstack/react-query';
import { deleteDomainGlueRecord, fetchDomainGlueRecords } from '../../data/domain-glue-records';
import {
DomainGlueRecord,
fetchDomainGlueRecords,
createDomainGlueRecord,
updateDomainGlueRecord,
deleteDomainGlueRecord,
} from '../../data/domain-glue-records';
import { queryClient } from '../query-client';

export const domainGlueRecordsQuery = ( domainName: string ) =>
Expand All @@ -8,10 +14,48 @@ export const domainGlueRecordsQuery = ( domainName: string ) =>
queryFn: () => fetchDomainGlueRecords( domainName ),
} );

export const domainGlueRecordCreateMutation = ( domainName: string ) =>
mutationOptions( {
mutationFn: ( glueRecord: DomainGlueRecord ) => createDomainGlueRecord( glueRecord ),
onSuccess: ( newData, createdGlueRecord ) => {
queryClient.setQueryData(
domainGlueRecordsQuery( domainName ).queryKey,
( oldData: DomainGlueRecord[] = [] ) => oldData.concat( [ createdGlueRecord ] )
);
queryClient.invalidateQueries( domainGlueRecordsQuery( domainName ) );
},
} );

export const domainGlueRecordUpdateMutation = ( domainName: string ) =>
mutationOptions( {
mutationFn: ( glueRecord: DomainGlueRecord ) => updateDomainGlueRecord( glueRecord ),
onSuccess: ( newData, updatedGlueRecord ) => {
queryClient.setQueryData(
domainGlueRecordsQuery( domainName ).queryKey,
( oldData: DomainGlueRecord[] = [] ) => {
return oldData.map( ( glueRecord ) => {
if ( glueRecord.nameserver === updatedGlueRecord.nameserver ) {
return updatedGlueRecord;
}

return glueRecord;
} );
}
);
queryClient.invalidateQueries( domainGlueRecordsQuery( domainName ) );
},
} );

export const domainGlueRecordDeleteMutation = ( domainName: string ) =>
mutationOptions( {
mutationFn: ( nameServer: string ) => deleteDomainGlueRecord( domainName, nameServer ),
onSuccess: () => {
mutationFn: ( glueRecord: DomainGlueRecord ) =>
deleteDomainGlueRecord( domainName, glueRecord ),
onSuccess: ( newData, deletedGlueRecord ): void => {
queryClient.setQueryData(
domainGlueRecordsQuery( domainName ).queryKey,
( oldData: DomainGlueRecord[] = [] ) =>
oldData.filter( ( glueRecord ) => glueRecord.nameserver !== deletedGlueRecord.nameserver )
);
queryClient.invalidateQueries( domainGlueRecordsQuery( domainName ) );
},
} );
22 changes: 18 additions & 4 deletions client/dashboard/app/router/domains.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { createRoute, createLazyRoute, redirect } from '@tanstack/react-router';
import { createRoute, createLazyRoute, notFound, redirect } from '@tanstack/react-router';
import { domainQuery } from '../queries/domain';
import { domainDnsQuery } from '../queries/domain-dns-records';
import { domainForwardingQuery } from '../queries/domain-forwarding';
Expand Down Expand Up @@ -168,7 +168,7 @@ export const domainGlueRecordsRoute = createRoute( {
loader: ( { params: { domainName } } ) =>
queryClient.ensureQueryData( domainGlueRecordsQuery( domainName ) ),
} ).lazy( () =>
import( '../../domains/overview-glue-records' ).then( ( d ) =>
import( '../../domains/domain-glue-records' ).then( ( d ) =>
createLazyRoute( 'domain-glue-records' )( {
component: d.default,
} )
Expand All @@ -179,7 +179,7 @@ export const domainGlueRecordsAddRoute = createRoute( {
getParentRoute: () => domainRoute,
path: 'glue-records/add',
} ).lazy( () =>
import( '../../sites/domains/placeholder' ).then( ( d ) =>
import( '../../domains/domain-glue-records/add' ).then( ( d ) =>
createLazyRoute( 'domain-glue-records-add' )( {
component: d.default,
} )
Expand All @@ -189,8 +189,22 @@ export const domainGlueRecordsAddRoute = createRoute( {
export const domainGlueRecordsEditRoute = createRoute( {
getParentRoute: () => domainRoute,
path: 'glue-records/edit/$nameServer',
beforeLoad: async ( { params: { domainName, nameServer } } ) => {
const glueRecordsData = await queryClient.ensureQueryData(
domainGlueRecordsQuery( domainName )
);
const glueRecord = glueRecordsData.find(
( glueRecord ) => glueRecord.nameserver === nameServer
);

if ( ! glueRecord ) {
throw notFound();
}
},
loader: ( { params: { domainName } } ) =>
queryClient.ensureQueryData( domainGlueRecordsQuery( domainName ) ),
} ).lazy( () =>
import( '../../sites/domains/placeholder' ).then( ( d ) =>
import( '../../domains/domain-glue-records/edit' ).then( ( d ) =>
createLazyRoute( 'domain-glue-records-edit' )( {
component: d.default,
} )
Expand Down
34 changes: 32 additions & 2 deletions client/dashboard/data/domain-glue-records.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,45 @@ export function fetchDomainGlueRecords( domainName: string ): Promise< DomainGlu
} );
}

export function deleteDomainGlueRecord( domainName: string, nameServer: string ): Promise< void > {
export function createDomainGlueRecord( glueRecord: DomainGlueRecord ): Promise< void > {
return wpcom.req.post(
{
path: '/domains/glue-records',
apiNamespace: 'wpcom/v2',
},
{
name_server: glueRecord.nameserver,
ip_addresses: glueRecord.ip_addresses,
}
);
}

export function updateDomainGlueRecord( glueRecord: DomainGlueRecord ): Promise< void > {
return wpcom.req.put(
{
path: '/domains/glue-records',
apiNamespace: 'wpcom/v2',
method: 'PUT',
},
{
name_server: glueRecord.nameserver,
ip_addresses: glueRecord.ip_addresses,
}
);
}

export function deleteDomainGlueRecord(
domainName: string,
glueRecord: DomainGlueRecord
): Promise< void > {
return wpcom.req.post(
{
path: `/domains/glue-records/${ domainName }`,
apiNamespace: 'wpcom/v2',
method: 'DELETE',
},
{
name_server: nameServer,
name_server: glueRecord.nameserver,
}
);
}
46 changes: 46 additions & 0 deletions client/dashboard/domains/domain-glue-records/add.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { useMutation } from '@tanstack/react-query';
import { useNavigate } from '@tanstack/react-router';
import { useDispatch } from '@wordpress/data';
import { __ } from '@wordpress/i18n';
import { store as noticesStore } from '@wordpress/notices';
import { domainGlueRecordCreateMutation } from '../../app/queries/domain-glue-records';
import { domainRoute, domainGlueRecordsRoute } from '../../app/router/domains';
import { PageHeader } from '../../components/page-header';
import PageLayout from '../../components/page-layout';
import { DomainGlueRecord } from '../../data/domain-glue-records';
import DomainGlueRecordsForm from './form';

export default function AddDomainGlueRecords() {
const navigate = useNavigate();
const { domainName } = domainRoute.useParams();
const createMutation = useMutation( domainGlueRecordCreateMutation( domainName ) );
const { createSuccessNotice, createErrorNotice } = useDispatch( noticesStore );

const handleSubmit = ( glueRecord: DomainGlueRecord ) => {
createMutation.mutate( glueRecord, {
onSuccess: () => {
createSuccessNotice( __( 'Glue record created successfully.' ), {
type: 'snackbar',
} );
navigate( {
to: domainGlueRecordsRoute.fullPath,
params: { domainName },
} );
},
onError: () => {
createErrorNotice( __( 'Failed to create glue record.' ), { type: 'snackbar' } );
},
} );
};

return (
<PageLayout size="small" header={ <PageHeader title={ __( 'Add glue record' ) } /> }>
<DomainGlueRecordsForm
domainName={ domainName }
onSubmit={ handleSubmit }
isSubmitting={ createMutation.isPending }
submitButtonText={ __( 'Add record' ) }
/>
</PageLayout>
);
}
55 changes: 55 additions & 0 deletions client/dashboard/domains/domain-glue-records/edit.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { useSuspenseQuery, useMutation } from '@tanstack/react-query';
import { useNavigate } from '@tanstack/react-router';
import { useDispatch } from '@wordpress/data';
import { __ } from '@wordpress/i18n';
import { store as noticesStore } from '@wordpress/notices';
import {
domainGlueRecordsQuery,
domainGlueRecordUpdateMutation,
} from '../../app/queries/domain-glue-records';
import { domainRoute, domainGlueRecordsRoute } from '../../app/router/domains';
import { PageHeader } from '../../components/page-header';
import PageLayout from '../../components/page-layout';
import { DomainGlueRecord } from '../../data/domain-glue-records';
import DomainGlueRecordsForm from './form';

export default function EditDomainGlueRecords() {
const navigate = useNavigate();
const { domainName, nameServer } = domainRoute.useParams();
const { data: glueRecordsData } = useSuspenseQuery( domainGlueRecordsQuery( domainName ) );
const updateMutation = useMutation( domainGlueRecordUpdateMutation( domainName ) );
const { createSuccessNotice, createErrorNotice } = useDispatch( noticesStore );
const glueRecord = glueRecordsData.find(
( glueRecord: DomainGlueRecord ) => glueRecord.nameserver === nameServer
);

const handleSubmit = ( updatedGlueRecord: DomainGlueRecord ) => {
updateMutation.mutate( updatedGlueRecord, {
onSuccess: () => {
createSuccessNotice( __( 'Glue record updated successfully.' ), {
type: 'snackbar',
} );
navigate( {
to: domainGlueRecordsRoute.fullPath,
params: { domainName },
} );
},
onError: () => {
createErrorNotice( __( 'Failed to update glue record.' ), { type: 'snackbar' } );
},
} );
};

return (
<PageLayout size="small" header={ <PageHeader title={ __( 'Edit glue record' ) } /> }>
<DomainGlueRecordsForm
domainName={ domainName }
initialData={ glueRecord }
onSubmit={ handleSubmit }
isSubmitting={ updateMutation.isPending }
isEdit
submitButtonText={ __( 'Update glue record' ) }
/>
</PageLayout>
);
}
Loading