-
Notifications
You must be signed in to change notification settings - Fork 2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Domains: Add Glue Records management UI (#84261)
* Add initial structure * Fix styles * Improve styles * Add feature flags * Replace `Remove` link with button * Improve loading state * Improve placeholder labels * Update field labels * Add limit of glue records * Improve react-query cached data * Include placeholder style * Force lowercase nameservers * Render `Add Glue Records` action only when necessary * Fix cancel button behavior * Lazy query * Improve data caching * Only show glue records card for domains registered with us * Fix comments * Validate record and IP address fields before saving glue record * Rename method `handleAddGlueRecord` to `showGlueRecordForm` * Fix comment * Add missing dependency for `useEffect` * Simplify condition * Only show glue records card for domains registered through Key-Systems * Add error validation message to glue record fields * Remove references to domain forwarding and simplify CSS * Fetch data when expanding card to prevent stale data from being shown --------- Co-authored-by: Leonardo Sameshima Taba <leonardo.taba@automattic.com>
- Loading branch information
1 parent
abe8454
commit 7ddfb9d
Showing
16 changed files
with
579 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
5 changes: 5 additions & 0 deletions
5
client/data/domains/glue-records/domain-glue-record-query-key.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
import { QueryKey } from '@tanstack/react-query'; | ||
|
||
export function domainGlueRecordQueryKey( domainName: string ): QueryKey { | ||
return [ 'glue-record', domainName ]; | ||
} |
54 changes: 54 additions & 0 deletions
54
client/data/domains/glue-records/use-delete-glue-record-mutation.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
import { useMutation, useQueryClient } from '@tanstack/react-query'; | ||
import { useCallback } from 'react'; | ||
import { domainGlueRecordQueryKey } from 'calypso/data/domains/glue-records/domain-glue-record-query-key'; | ||
import { | ||
GlueRecordObject, | ||
GlueRecordQueryData, | ||
} from 'calypso/data/domains/glue-records/use-domain-glue-records-query'; | ||
import { DomainsApiError } from 'calypso/lib/domains/types'; | ||
import wp from 'calypso/lib/wp'; | ||
|
||
export default function useDeleteGlueRecordMutation( | ||
domainName: string, | ||
queryOptions: { | ||
onSuccess?: () => void; | ||
onError?: ( error: DomainsApiError ) => void; | ||
} | ||
) { | ||
const queryClient = useQueryClient(); | ||
const mutation = useMutation( { | ||
mutationFn: ( glueRecord: GlueRecordObject ) => | ||
wp.req | ||
.post( | ||
{ | ||
path: `/domains/glue-records/${ domainName }`, | ||
apiNamespace: 'wpcom/v2', | ||
method: 'DELETE', | ||
}, | ||
{ | ||
name_server: glueRecord.record, | ||
} | ||
) | ||
.then( () => glueRecord ), | ||
...queryOptions, | ||
onSuccess( glueRecord: GlueRecordObject ) { | ||
const key = domainGlueRecordQueryKey( domainName ); | ||
queryClient.setQueryData( key, ( old: GlueRecordQueryData ) => { | ||
if ( ! old ) { | ||
return []; | ||
} | ||
return old.filter( ( item ) => item.nameserver !== glueRecord.record ); | ||
} ); | ||
queryOptions.onSuccess?.(); | ||
}, | ||
} ); | ||
|
||
const { mutate } = mutation; | ||
|
||
const deleteGlueRecord = useCallback( | ||
( glueRecord: GlueRecordObject ) => mutate( glueRecord ), | ||
[ mutate ] | ||
); | ||
|
||
return { deleteGlueRecord, ...mutation }; | ||
} |
56 changes: 56 additions & 0 deletions
56
client/data/domains/glue-records/use-domain-glue-records-query.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
import { UseQueryResult, useQuery } from '@tanstack/react-query'; | ||
import wp from 'calypso/lib/wp'; | ||
import { domainGlueRecordQueryKey } from './domain-glue-record-query-key'; | ||
|
||
export type Maybe< T > = T | null | undefined; | ||
export type GlueRecordResponse = GlueRecordObject[] | null | undefined; | ||
|
||
export type GlueRecordObject = { | ||
record: string; | ||
address: string; | ||
}; | ||
|
||
export type GlueRecordQueryData = Maybe< GlueRecordApiObject[] >; | ||
|
||
export type GlueRecordApiObject = { | ||
nameserver: string; | ||
ip_addresses: string[]; | ||
}; | ||
|
||
export const mapGlueRecordObjectToApiObject = ( record: GlueRecordObject ): GlueRecordApiObject => { | ||
return { | ||
nameserver: record.record.toLowerCase(), | ||
ip_addresses: [ record.address ], | ||
}; | ||
}; | ||
|
||
const selectGlueRecords = ( response: GlueRecordApiObject[] | null ): GlueRecordResponse => { | ||
if ( ! response ) { | ||
return null; | ||
} | ||
|
||
return response?.map( ( record: GlueRecordApiObject ) => { | ||
return { | ||
record: record.nameserver.toLowerCase(), | ||
address: record.ip_addresses[ 0 ], | ||
}; | ||
} ); | ||
}; | ||
|
||
export default function useDomainGlueRecordsQuery( | ||
domainName: string | ||
): UseQueryResult< GlueRecordResponse > { | ||
return useQuery( { | ||
queryKey: domainGlueRecordQueryKey( domainName ), | ||
queryFn: () => | ||
wp.req.get( { | ||
path: `/domains/glue-records/${ domainName }`, | ||
apiNamespace: 'wpcom/v2', | ||
} ), | ||
refetchOnWindowFocus: false, | ||
select: selectGlueRecords, | ||
enabled: false, | ||
staleTime: 5 * 60 * 1000, | ||
cacheTime: 5 * 60 * 1000, | ||
} ); | ||
} |
58 changes: 58 additions & 0 deletions
58
client/data/domains/glue-records/use-update-glue-record-mutation.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
import { useMutation, useQueryClient } from '@tanstack/react-query'; | ||
import { useCallback } from 'react'; | ||
import { domainGlueRecordQueryKey } from 'calypso/data/domains/glue-records/domain-glue-record-query-key'; | ||
import { DomainsApiError } from 'calypso/lib/domains/types'; | ||
import wp from 'calypso/lib/wp'; | ||
import { | ||
GlueRecordObject, | ||
GlueRecordQueryData, | ||
mapGlueRecordObjectToApiObject, | ||
} from './use-domain-glue-records-query'; | ||
|
||
export default function useUpdateGlueRecordMutation( | ||
domainName: string, | ||
queryOptions: { | ||
onSuccess?: () => void; | ||
onError?: ( error: DomainsApiError ) => void; | ||
} | ||
) { | ||
const queryClient = useQueryClient(); | ||
const mutation = useMutation( { | ||
mutationFn: ( glueRecord: GlueRecordObject ) => | ||
wp.req | ||
.post( | ||
{ | ||
path: `/domains/glue-records`, | ||
apiNamespace: 'wpcom/v2', | ||
}, | ||
{ | ||
name_server: glueRecord.record.toLowerCase(), | ||
ip_addresses: [ glueRecord.address ], | ||
} | ||
) | ||
.then( () => glueRecord ), | ||
...queryOptions, | ||
onSuccess( glueRecord: GlueRecordObject ) { | ||
const key = domainGlueRecordQueryKey( domainName ); | ||
queryClient.setQueryData( key, ( old: GlueRecordQueryData ) => { | ||
if ( ! old ) { | ||
return [ mapGlueRecordObjectToApiObject( glueRecord ) ]; | ||
} | ||
return [ ...old, mapGlueRecordObjectToApiObject( glueRecord ) ]; | ||
} ); | ||
queryOptions.onSuccess?.(); | ||
}, | ||
onError( error: DomainsApiError ) { | ||
queryOptions.onError?.( error ); | ||
}, | ||
} ); | ||
|
||
const { mutate } = mutation; | ||
|
||
const updateGlueRecord = useCallback( | ||
( glueRecord: GlueRecordObject ) => mutate( glueRecord ), | ||
[ mutate ] | ||
); | ||
|
||
return { updateGlueRecord, ...mutation }; | ||
} |
Oops, something went wrong.