Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add VPC, Subnet to NIC table #1047

Merged
merged 11 commits into from
Jul 21, 2022
10 changes: 8 additions & 2 deletions app/pages/project/instances/instance/tabs/NetworkingTab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { useState } from 'react'
import type { NetworkInterface, NetworkInterfaceUpdate } from '@oxide/api'
import { useApiMutation, useApiQuery, useApiQueryClient } from '@oxide/api'
import type { MenuAction } from '@oxide/table'
import { useQueryTable } from '@oxide/table'
import { byIdCell, useQueryTable } from '@oxide/table'
import {
Badge,
Button,
Expand Down Expand Up @@ -93,11 +93,17 @@ export function NetworkingTab() {
<h2 id="network-interfaces" className="mb-4 text-mono-sm text-secondary">
Network Interfaces
</h2>
<Table makeActions={makeActions} emptyState={emptyState}>
<Table debug makeActions={makeActions} emptyState={emptyState}>
<Column accessor="name" />
<Column accessor="description" />
{/* TODO: mark v4 or v6 explicitly? */}
<Column accessor="ip" />
<Column header="vpc" accessor="vpcId" cell={byIdCell('vpcViewById', 'name')} />
<Column
header="subnet"
accessor="subnetId"
cell={byIdCell('vpcSubnetViewById', 'name')}
/>
<Column
accessor="primary"
cell={({ value }) =>
Expand Down
44 changes: 44 additions & 0 deletions libs/api/__generated__/Api.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 1 addition & 12 deletions libs/api/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
import type * as ApiTypes from './__generated__/Api'
import { Api } from './__generated__/Api'
import { handleErrors } from './errors'
import type { ResultItem } from './hooks'
import { getUseApiMutation, getUseApiQuery, getUseApiQueryClient } from './hooks'

const api = new Api({
Expand All @@ -11,17 +10,7 @@ const api = new Api({

export type ApiMethods = typeof api.methods

/**
* API methods that return a list of items.
*/
export type ApiListMethods = {
// Only never extends never. If ResultItem extends never, that means we
// couldn't pull out an item, which means it's not a list endpoint. If we can
// infer an item, that means it's a list endpoint, so include its M.
[M in keyof ApiMethods as ResultItem<ApiMethods[M]> extends never
? never
: M]: ApiMethods[M]
}
export { ApiListMethods, ApiViewByIdMethods } from './__generated__/Api'

export const useApiQuery = getUseApiQuery(api.methods, handleErrors)
export const useApiMutation = getUseApiMutation(api.methods, handleErrors)
Expand Down
2 changes: 1 addition & 1 deletion libs/table/QueryTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ const makeQueryTable = <Item,>(
manualPagination: true,
})

if (debug) console.table(data)
if (debug) console.table((data as { items?: any[] })?.items || data)

const paginationParams = useMemo(
() => ({
Expand Down
30 changes: 30 additions & 0 deletions libs/table/cells/IdLookupCell.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import React from 'react'
import type { AsyncReturnType } from 'type-fest'

import type { ApiViewByIdMethods } from '@oxide/api'
import { useApiQuery } from '@oxide/api'

import type { Cell } from './Cell'

interface IdLookupCellProps<M extends keyof ApiViewByIdMethods> {
type: M
field: keyof NonNullable<AsyncReturnType<ApiViewByIdMethods[M]>['data']>
value: string
}
Copy link
Collaborator

@david-crespo david-crespo Jul 21, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I spent some time trying to get the approach that works for useApiQuery to work here — no dice. So annoying.

-interface IdLookupCellProps<M extends keyof ApiViewByIdMethods> {
+interface IdLookupCellProps<A extends ApiViewByIdMethods, M extends keyof A> {
   type: M
-  field: keyof NonNullable<AsyncReturnType<ApiViewByIdMethods[M]>['data']>
+  field: keyof NonNullable<AsyncReturnType<A[M]>['data']>
   value: string
 }
-function IdLookupCell<M extends keyof ApiViewByIdMethods>({
+
+function IdLookupCell<A extends ApiViewByIdMethods, M extends keyof A>({
   type,
   field,
   value,
-}: IdLookupCellProps<M>) {
-  // @ts-expect-error TODO M isn't correctly narrowing the type down
-  const { data } = useApiQuery<M>(type, { id: value })
+}: IdLookupCellProps<A, M>) {
+  const { data } = useApiQuery<M>(type as M, { id: value })
   // @ts-expect-error TODO Because data isn't narrowed correctly above this is an error too
   return (data && <span className="text-default">{data[field]}</span>) || null
 }
 
-export const byIdCell =
-  <M extends keyof ApiViewByIdMethods>(
-    type: IdLookupCellProps<M>['type'],
-    field: IdLookupCellProps<M>['field']
+const getByIdCell =
+  <A extends ApiViewByIdMethods>() =>
+  <M extends keyof A>(
+    type: IdLookupCellProps<A, M>['type'],
+    field: IdLookupCellProps<A, M>['field']
   ) =>
   ({ value }: Cell<string>) => {
     return <IdLookupCell type={type} field={field} value={value} />
   }
+
+export const byIdCell = getByIdCell()

function IdLookupCell<M extends keyof ApiViewByIdMethods>({
type,
field,
value,
}: IdLookupCellProps<M>) {
const { data } = useApiQuery<M>(type, { id: value })
return (data && <span className="text-default">{data[field]}</span>) || null
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The outside types are correct, but these inner types are fucked.

}

export const byIdCell =
<M extends keyof ApiViewByIdMethods>(
type: IdLookupCellProps<M>['type'],
field: IdLookupCellProps<M>['field']
) =>
({ value }: Cell<string>) => {
return <IdLookupCell type={type} field={field} value={value} />
}
1 change: 1 addition & 0 deletions libs/table/cells/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ export * from './SizeCell'
export * from './TwoLineCell'
export * from './TypeValueCell'
export * from './TypeValueListCell'
export * from './IdLookupCell'