feat: Bring back API key sales channel management (#6976)
- Add API key sales channel management - Add HTTP responses for API keys and sales channels - Use HTTP responses in `dashboard` and remove now redundant types
This commit is contained in:
@@ -10,11 +10,9 @@ import { client } from "../../lib/client"
|
||||
import { queryClient } from "../../lib/medusa"
|
||||
import { queryKeysFactory } from "../../lib/query-key-factory"
|
||||
import { CreateApiKeyReq, UpdateApiKeyReq } from "../../types/api-payloads"
|
||||
import {
|
||||
ApiKeyDeleteRes,
|
||||
ApiKeyListRes,
|
||||
ApiKeyRes,
|
||||
} from "../../types/api-responses"
|
||||
import { ApiKeyDeleteRes } from "../../types/api-responses"
|
||||
import { AdminApiKeyResponse, AdminApiKeyListResponse } from "@medusajs/types"
|
||||
import { salesChannelsQueryKeys } from "./sales-channels"
|
||||
|
||||
const API_KEYS_QUERY_KEY = "api_keys" as const
|
||||
export const apiKeysQueryKeys = queryKeysFactory(API_KEYS_QUERY_KEY)
|
||||
@@ -23,7 +21,7 @@ export const useApiKey = (
|
||||
id: string,
|
||||
query?: Record<string, any>,
|
||||
options?: Omit<
|
||||
UseQueryOptions<ApiKeyRes, Error, ApiKeyRes, QueryKey>,
|
||||
UseQueryOptions<AdminApiKeyResponse, Error, AdminApiKeyResponse, QueryKey>,
|
||||
"queryKey" | "queryFn"
|
||||
>
|
||||
) => {
|
||||
@@ -39,7 +37,12 @@ export const useApiKey = (
|
||||
export const useApiKeys = (
|
||||
query?: Record<string, any>,
|
||||
options?: Omit<
|
||||
UseQueryOptions<ApiKeyListRes, Error, ApiKeyListRes, QueryKey>,
|
||||
UseQueryOptions<
|
||||
AdminApiKeyListResponse,
|
||||
Error,
|
||||
AdminApiKeyListResponse,
|
||||
QueryKey
|
||||
>,
|
||||
"queryKey" | "queryFn"
|
||||
>
|
||||
) => {
|
||||
@@ -53,7 +56,7 @@ export const useApiKeys = (
|
||||
}
|
||||
|
||||
export const useCreateApiKey = (
|
||||
options?: UseMutationOptions<ApiKeyRes, Error, CreateApiKeyReq>
|
||||
options?: UseMutationOptions<AdminApiKeyResponse, Error, CreateApiKeyReq>
|
||||
) => {
|
||||
return useMutation({
|
||||
mutationFn: (payload) => client.apiKeys.create(payload),
|
||||
@@ -68,7 +71,7 @@ export const useCreateApiKey = (
|
||||
|
||||
export const useUpdateApiKey = (
|
||||
id: string,
|
||||
options?: UseMutationOptions<ApiKeyRes, Error, UpdateApiKeyReq>
|
||||
options?: UseMutationOptions<AdminApiKeyResponse, Error, UpdateApiKeyReq>
|
||||
) => {
|
||||
return useMutation({
|
||||
mutationFn: (payload) => client.apiKeys.update(id, payload),
|
||||
@@ -84,7 +87,7 @@ export const useUpdateApiKey = (
|
||||
|
||||
export const useRevokeApiKey = (
|
||||
id: string,
|
||||
options?: UseMutationOptions<ApiKeyRes, Error, void>
|
||||
options?: UseMutationOptions<AdminApiKeyResponse, Error, void>
|
||||
) => {
|
||||
return useMutation({
|
||||
mutationFn: () => client.apiKeys.revoke(id),
|
||||
@@ -111,3 +114,50 @@ export const useDeleteApiKey = (
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
export const useBatchRemoveSalesChannelsFromApiKey = (
|
||||
id: string,
|
||||
options?: UseMutationOptions<
|
||||
AdminApiKeyResponse,
|
||||
Error,
|
||||
{ sales_channel_ids: string[] }
|
||||
>
|
||||
) => {
|
||||
return useMutation({
|
||||
mutationFn: (payload) =>
|
||||
client.apiKeys.batchRemoveSalesChannels(id, payload),
|
||||
onSuccess: (data, variables, context) => {
|
||||
queryClient.invalidateQueries({ queryKey: apiKeysQueryKeys.lists() })
|
||||
queryClient.invalidateQueries({ queryKey: apiKeysQueryKeys.detail(id) })
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: salesChannelsQueryKeys.lists(),
|
||||
})
|
||||
|
||||
options?.onSuccess?.(data, variables, context)
|
||||
},
|
||||
...options,
|
||||
})
|
||||
}
|
||||
|
||||
export const useBatchAddSalesChannelsToApiKey = (
|
||||
id: string,
|
||||
options?: UseMutationOptions<
|
||||
AdminApiKeyResponse,
|
||||
Error,
|
||||
{ sales_channel_ids: string[] }
|
||||
>
|
||||
) => {
|
||||
return useMutation({
|
||||
mutationFn: (payload) => client.apiKeys.batchAddSalesChannels(id, payload),
|
||||
onSuccess: (data, variables, context) => {
|
||||
queryClient.invalidateQueries({ queryKey: apiKeysQueryKeys.lists() })
|
||||
queryClient.invalidateQueries({ queryKey: apiKeysQueryKeys.detail(id) })
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: salesChannelsQueryKeys.lists(),
|
||||
})
|
||||
|
||||
options?.onSuccess?.(data, variables, context)
|
||||
},
|
||||
...options,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -15,20 +15,25 @@ import {
|
||||
RemoveProductsSalesChannelReq,
|
||||
UpdateSalesChannelReq,
|
||||
} from "../../types/api-payloads"
|
||||
import {
|
||||
SalesChannelDeleteRes,
|
||||
SalesChannelListRes,
|
||||
SalesChannelRes,
|
||||
} from "../../types/api-responses"
|
||||
import { SalesChannelDeleteRes } from "../../types/api-responses"
|
||||
import { productsQueryKeys } from "./products"
|
||||
import {
|
||||
AdminSalesChannelListResponse,
|
||||
AdminSalesChannelResponse,
|
||||
} from "@medusajs/types"
|
||||
|
||||
const SALES_CHANNELS_QUERY_KEY = "sales-channels" as const
|
||||
const salesChannelsQueryKeys = queryKeysFactory(SALES_CHANNELS_QUERY_KEY)
|
||||
export const salesChannelsQueryKeys = queryKeysFactory(SALES_CHANNELS_QUERY_KEY)
|
||||
|
||||
export const useSalesChannel = (
|
||||
id: string,
|
||||
options?: Omit<
|
||||
UseQueryOptions<SalesChannelRes, Error, SalesChannelRes, QueryKey>,
|
||||
UseQueryOptions<
|
||||
AdminSalesChannelResponse,
|
||||
Error,
|
||||
AdminSalesChannelResponse,
|
||||
QueryKey
|
||||
>,
|
||||
"queryFn" | "queryKey"
|
||||
>
|
||||
) => {
|
||||
@@ -44,7 +49,12 @@ export const useSalesChannel = (
|
||||
export const useSalesChannels = (
|
||||
query?: Record<string, any>,
|
||||
options?: Omit<
|
||||
UseQueryOptions<SalesChannelListRes, Error, SalesChannelListRes, QueryKey>,
|
||||
UseQueryOptions<
|
||||
AdminSalesChannelListResponse,
|
||||
Error,
|
||||
AdminSalesChannelListResponse,
|
||||
QueryKey
|
||||
>,
|
||||
"queryFn" | "queryKey"
|
||||
>
|
||||
) => {
|
||||
@@ -58,7 +68,11 @@ export const useSalesChannels = (
|
||||
}
|
||||
|
||||
export const useCreateSalesChannel = (
|
||||
options?: UseMutationOptions<SalesChannelRes, Error, CreateSalesChannelReq>
|
||||
options?: UseMutationOptions<
|
||||
AdminSalesChannelResponse,
|
||||
Error,
|
||||
CreateSalesChannelReq
|
||||
>
|
||||
) => {
|
||||
return useMutation({
|
||||
mutationFn: (payload) => client.salesChannels.create(payload),
|
||||
@@ -74,7 +88,11 @@ export const useCreateSalesChannel = (
|
||||
|
||||
export const useUpdateSalesChannel = (
|
||||
id: string,
|
||||
options?: UseMutationOptions<SalesChannelRes, Error, UpdateSalesChannelReq>
|
||||
options?: UseMutationOptions<
|
||||
AdminSalesChannelResponse,
|
||||
Error,
|
||||
UpdateSalesChannelReq
|
||||
>
|
||||
) => {
|
||||
return useMutation({
|
||||
mutationFn: (payload) => client.salesChannels.update(id, payload),
|
||||
@@ -120,7 +138,7 @@ export const useDeleteSalesChannel = (
|
||||
export const useSalesChannelRemoveProducts = (
|
||||
id: string,
|
||||
options?: UseMutationOptions<
|
||||
SalesChannelRes,
|
||||
AdminSalesChannelResponse,
|
||||
Error,
|
||||
RemoveProductsSalesChannelReq
|
||||
>
|
||||
@@ -156,7 +174,7 @@ export const useSalesChannelRemoveProducts = (
|
||||
export const useSalesChannelAddProducts = (
|
||||
id: string,
|
||||
options?: UseMutationOptions<
|
||||
SalesChannelRes,
|
||||
AdminSalesChannelResponse,
|
||||
Error,
|
||||
AddProductsSalesChannelReq
|
||||
>
|
||||
|
||||
@@ -1,17 +1,14 @@
|
||||
import { AdminApiKeyListResponse, AdminApiKeyResponse } from "@medusajs/types"
|
||||
import { CreateApiKeyReq, UpdateApiKeyReq } from "../../types/api-payloads"
|
||||
import {
|
||||
ApiKeyDeleteRes,
|
||||
ApiKeyListRes,
|
||||
ApiKeyRes,
|
||||
} from "../../types/api-responses"
|
||||
import { ApiKeyDeleteRes } from "../../types/api-responses"
|
||||
import { deleteRequest, getRequest, postRequest } from "./common"
|
||||
|
||||
const retrieveApiKey = async (id: string, query?: Record<string, any>) => {
|
||||
return getRequest<ApiKeyRes>(`/admin/api-keys/${id}`, query)
|
||||
return getRequest<AdminApiKeyResponse>(`/admin/api-keys/${id}`, query)
|
||||
}
|
||||
|
||||
const listApiKeys = async (query?: Record<string, any>) => {
|
||||
return getRequest<ApiKeyListRes>(`/admin/api-keys`, query)
|
||||
return getRequest<AdminApiKeyListResponse>(`/admin/api-keys`, query)
|
||||
}
|
||||
|
||||
const deleteApiKey = async (id: string) => {
|
||||
@@ -19,15 +16,35 @@ const deleteApiKey = async (id: string) => {
|
||||
}
|
||||
|
||||
const revokeApiKey = async (id: string) => {
|
||||
return postRequest<ApiKeyRes>(`/admin/api-keys/${id}/revoke`)
|
||||
return postRequest<AdminApiKeyResponse>(`/admin/api-keys/${id}/revoke`)
|
||||
}
|
||||
|
||||
const createApiKey = async (payload: CreateApiKeyReq) => {
|
||||
return postRequest<ApiKeyRes>(`/admin/api-keys`, payload)
|
||||
return postRequest<AdminApiKeyResponse>(`/admin/api-keys`, payload)
|
||||
}
|
||||
|
||||
const updateApiKey = async (id: string, payload: UpdateApiKeyReq) => {
|
||||
return postRequest<ApiKeyRes>(`/admin/api-keys/${id}`, payload)
|
||||
return postRequest<AdminApiKeyResponse>(`/admin/api-keys/${id}`, payload)
|
||||
}
|
||||
|
||||
const batchRemoveSalesChannelsFromApiKey = async (
|
||||
id: string,
|
||||
payload: { sales_channel_ids: string[] }
|
||||
) => {
|
||||
return postRequest<AdminApiKeyResponse>(
|
||||
`/admin/api-keys/${id}/sales-channels/batch/remove`,
|
||||
payload
|
||||
)
|
||||
}
|
||||
|
||||
const batchAddSalesChannelsFromApiKey = async (
|
||||
id: string,
|
||||
payload: { sales_channel_ids: string[] }
|
||||
) => {
|
||||
return postRequest<AdminApiKeyResponse>(
|
||||
`/admin/api-keys/${id}/sales-channels/batch/add`,
|
||||
payload
|
||||
)
|
||||
}
|
||||
|
||||
export const apiKeys = {
|
||||
@@ -37,4 +54,6 @@ export const apiKeys = {
|
||||
create: createApiKey,
|
||||
update: updateApiKey,
|
||||
revoke: revokeApiKey,
|
||||
batchRemoveSalesChannels: batchRemoveSalesChannelsFromApiKey,
|
||||
batchAddSalesChannels: batchAddSalesChannelsFromApiKey,
|
||||
}
|
||||
|
||||
@@ -1,36 +1,42 @@
|
||||
import {
|
||||
AdminSalesChannelListResponse,
|
||||
AdminSalesChannelResponse,
|
||||
} from "@medusajs/types"
|
||||
import {
|
||||
AddProductsSalesChannelReq,
|
||||
CreateSalesChannelReq,
|
||||
RemoveProductsSalesChannelReq,
|
||||
UpdateSalesChannelReq,
|
||||
} from "../../types/api-payloads"
|
||||
import {
|
||||
SalesChannelDeleteRes,
|
||||
SalesChannelListRes,
|
||||
SalesChannelRes,
|
||||
} from "../../types/api-responses"
|
||||
import { SalesChannelDeleteRes } from "../../types/api-responses"
|
||||
import { deleteRequest, getRequest, postRequest } from "./common"
|
||||
|
||||
async function retrieveSalesChannel(id: string, query?: Record<string, any>) {
|
||||
return getRequest<SalesChannelRes, Record<string, any>>(
|
||||
return getRequest<AdminSalesChannelResponse, Record<string, any>>(
|
||||
`/admin/sales-channels/${id}`,
|
||||
query
|
||||
)
|
||||
}
|
||||
|
||||
async function listSalesChannels(query?: Record<string, any>) {
|
||||
return getRequest<SalesChannelListRes, Record<string, any>>(
|
||||
return getRequest<AdminSalesChannelListResponse, Record<string, any>>(
|
||||
`/admin/sales-channels`,
|
||||
query
|
||||
)
|
||||
}
|
||||
|
||||
async function createSalesChannel(payload: CreateSalesChannelReq) {
|
||||
return postRequest<SalesChannelRes>(`/admin/sales-channels`, payload)
|
||||
return postRequest<AdminSalesChannelResponse>(
|
||||
`/admin/sales-channels`,
|
||||
payload
|
||||
)
|
||||
}
|
||||
|
||||
async function updateSalesChannel(id: string, payload: UpdateSalesChannelReq) {
|
||||
return postRequest<SalesChannelRes>(`/admin/sales-channels/${id}`, payload)
|
||||
return postRequest<AdminSalesChannelResponse>(
|
||||
`/admin/sales-channels/${id}`,
|
||||
payload
|
||||
)
|
||||
}
|
||||
|
||||
async function deleteSalesChannel(id: string) {
|
||||
@@ -41,7 +47,7 @@ async function batchRemoveProducts(
|
||||
id: string,
|
||||
payload: RemoveProductsSalesChannelReq
|
||||
) {
|
||||
return postRequest<SalesChannelRes>(
|
||||
return postRequest<AdminSalesChannelResponse>(
|
||||
`/admin/sales-channels/${id}/products/batch/remove`,
|
||||
payload
|
||||
)
|
||||
@@ -51,7 +57,7 @@ async function batchAddProducts(
|
||||
id: string,
|
||||
payload: AddProductsSalesChannelReq
|
||||
) {
|
||||
return postRequest<SalesChannelRes>(
|
||||
return postRequest<AdminSalesChannelResponse>(
|
||||
`/admin/sales-channels/${id}/products/batch/add`,
|
||||
payload
|
||||
)
|
||||
|
||||
@@ -7,7 +7,7 @@ import { ErrorBoundary } from "../../components/error/error-boundary"
|
||||
import { MainLayout } from "../../components/layout-v2/main-layout"
|
||||
import { SettingsLayout } from "../../components/layout/settings-layout"
|
||||
import { useMe } from "../../hooks/api/users"
|
||||
import { ApiKeyRes } from "../../types/api-responses"
|
||||
import { AdminApiKeyResponse } from "@medusajs/types"
|
||||
import { SearchProvider } from "../search-provider"
|
||||
import { SidebarProvider } from "../sidebar-provider"
|
||||
|
||||
@@ -489,8 +489,7 @@ export const v2Routes: RouteObject[] = [
|
||||
"../../v2-routes/api-key-management/api-key-management-detail"
|
||||
),
|
||||
handle: {
|
||||
crumb: (data: ApiKeyRes) => {
|
||||
console.log("data", data)
|
||||
crumb: (data: AdminApiKeyResponse) => {
|
||||
return data.api_key.title
|
||||
},
|
||||
},
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
*/
|
||||
|
||||
import {
|
||||
ApiKeyDTO,
|
||||
CampaignDTO,
|
||||
CurrencyDTO,
|
||||
CustomerDTO,
|
||||
@@ -22,8 +21,8 @@ import {
|
||||
StoreDTO,
|
||||
UserDTO,
|
||||
} from "@medusajs/types"
|
||||
import { WorkflowExecutionDTO } from "../v2-routes/workflow-executions/types"
|
||||
import { ProductTagDTO } from "@medusajs/types/dist/product"
|
||||
import { WorkflowExecutionDTO } from "../v2-routes/workflow-executions/types"
|
||||
|
||||
type ListRes = {
|
||||
count: number
|
||||
@@ -77,18 +76,9 @@ export type CampaignListRes = { campaigns: CampaignDTO[] } & ListRes
|
||||
export type CampaignDeleteRes = DeleteRes
|
||||
|
||||
// API Keys
|
||||
export type ExtendedApiKeyDTO = ApiKeyDTO & {
|
||||
sales_channels: SalesChannelDTO[] | null
|
||||
}
|
||||
export type ApiKeyRes = { api_key: ExtendedApiKeyDTO }
|
||||
export type ApiKeyListRes = { api_keys: ExtendedApiKeyDTO[] } & ListRes
|
||||
export type ApiKeyDeleteRes = DeleteRes
|
||||
|
||||
// Sales Channels
|
||||
export type SalesChannelRes = { sales_channel: SalesChannelDTO }
|
||||
export type SalesChannelListRes = {
|
||||
sales_channels: SalesChannelDTO[]
|
||||
} & ListRes
|
||||
export type SalesChannelDeleteRes = DeleteRes
|
||||
|
||||
// Currencies
|
||||
|
||||
@@ -1,37 +1,27 @@
|
||||
// Missing Sales Channel endpoint for API Key domain
|
||||
|
||||
import { useParams } from "react-router-dom"
|
||||
import { RouteFocusModal } from "../../../components/route-modal"
|
||||
import { useSalesChannels } from "../../../hooks/api/sales-channels"
|
||||
import { AddSalesChannelsToApiKeyForm } from "./components"
|
||||
|
||||
export const ApiKeyManagementAddSalesChannels = () => {
|
||||
const { id } = useParams()
|
||||
|
||||
// const { data, isLoading, isError, error } = useAdminCustomQuery(
|
||||
// `/api-keys/${id}`,
|
||||
// [adminPublishableApiKeysKeys.detailSalesChannels(id!)],
|
||||
// {
|
||||
// fields: "id,*sales_channels",
|
||||
// },
|
||||
// {
|
||||
// keepPreviousData: true,
|
||||
// }
|
||||
// )
|
||||
const { sales_channels, isLoading, isError, error } = useSalesChannels({
|
||||
publishable_key_id: id,
|
||||
})
|
||||
|
||||
// if (isError) {
|
||||
// throw error
|
||||
// }
|
||||
|
||||
// const salesChannels = data?.api_key?.sales_channels
|
||||
if (isError) {
|
||||
throw error
|
||||
}
|
||||
|
||||
return (
|
||||
<RouteFocusModal>
|
||||
{/* {!isLoading && salesChannels && (
|
||||
{!isLoading && !!sales_channels && (
|
||||
<AddSalesChannelsToApiKeyForm
|
||||
apiKey={id!}
|
||||
preSelected={salesChannels.map((sc) => sc.id)}
|
||||
preSelected={sales_channels.map((sc) => sc.id)}
|
||||
/>
|
||||
)} */}
|
||||
TODO
|
||||
)}
|
||||
</RouteFocusModal>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,40 +1,25 @@
|
||||
import { zodResolver } from "@hookform/resolvers/zod"
|
||||
import { SalesChannel } from "@medusajs/medusa"
|
||||
import { Button, Checkbox, Hint, StatusBadge, Tooltip } from "@medusajs/ui"
|
||||
import {
|
||||
Button,
|
||||
Checkbox,
|
||||
Hint,
|
||||
StatusBadge,
|
||||
Table,
|
||||
Tooltip,
|
||||
clx,
|
||||
} from "@medusajs/ui"
|
||||
import {
|
||||
PaginationState,
|
||||
OnChangeFn,
|
||||
RowSelectionState,
|
||||
createColumnHelper,
|
||||
flexRender,
|
||||
getCoreRowModel,
|
||||
useReactTable,
|
||||
} from "@tanstack/react-table"
|
||||
import {
|
||||
adminPublishableApiKeysKeys,
|
||||
useAdminAddPublishableKeySalesChannelsBatch,
|
||||
useAdminCustomPost,
|
||||
useAdminSalesChannels,
|
||||
} from "medusa-react"
|
||||
import { useEffect, useMemo, useState } from "react"
|
||||
import { useMemo, useState } from "react"
|
||||
import { useForm } from "react-hook-form"
|
||||
import { useTranslation } from "react-i18next"
|
||||
import * as zod from "zod"
|
||||
import { OrderBy } from "../../../../components/filtering/order-by"
|
||||
import { Query } from "../../../../components/filtering/query"
|
||||
import { LocalizedTablePagination } from "../../../../components/localization/localized-table-pagination"
|
||||
import {
|
||||
RouteFocusModal,
|
||||
useRouteModal,
|
||||
} from "../../../../components/route-modal"
|
||||
import { useQueryParams } from "../../../../hooks/use-query-params"
|
||||
import { useBatchAddSalesChannelsToApiKey } from "../../../../hooks/api/api-keys"
|
||||
import { useSalesChannelTableQuery } from "../../../../hooks/table/query/use-sales-channel-table-query"
|
||||
import { useDataTable } from "../../../../hooks/use-data-table"
|
||||
import { useSalesChannels } from "../../../../hooks/api/sales-channels"
|
||||
import { keepPreviousData } from "@tanstack/react-query"
|
||||
import { DataTable } from "../../../../components/table/data-table"
|
||||
import { AdminSalesChannelResponse } from "@medusajs/types"
|
||||
|
||||
type AddSalesChannelsToApiKeyFormProps = {
|
||||
apiKey: string
|
||||
@@ -63,69 +48,51 @@ export const AddSalesChannelsToApiKeyForm = ({
|
||||
|
||||
const { setValue } = form
|
||||
|
||||
const { mutateAsync, isLoading: isMutating } = useAdminCustomPost(
|
||||
`/api-keys/${apiKey}/sales-channels/batch/add`,
|
||||
[adminPublishableApiKeysKeys.detailSalesChannels(apiKey)]
|
||||
)
|
||||
const [rowSelection, setRowSelection] = useState<RowSelectionState>({})
|
||||
|
||||
const [{ pageIndex, pageSize }, setPagination] = useState<PaginationState>({
|
||||
pageIndex: 0,
|
||||
// @ts-ignore
|
||||
const { mutateAsync, isLoading: isMutating } =
|
||||
useBatchAddSalesChannelsToApiKey(apiKey)
|
||||
|
||||
const { raw, searchParams } = useSalesChannelTableQuery({
|
||||
pageSize: PAGE_SIZE,
|
||||
})
|
||||
|
||||
const pagination = useMemo(
|
||||
() => ({
|
||||
pageIndex,
|
||||
pageSize,
|
||||
}),
|
||||
[pageIndex, pageSize]
|
||||
)
|
||||
const columns = useColumns()
|
||||
|
||||
const [rowSelection, setRowSelection] = useState<RowSelectionState>({})
|
||||
|
||||
useEffect(() => {
|
||||
setValue(
|
||||
"sales_channel_ids",
|
||||
Object.keys(rowSelection).filter((k) => rowSelection[k]),
|
||||
{
|
||||
shouldDirty: true,
|
||||
shouldTouch: true,
|
||||
}
|
||||
)
|
||||
}, [rowSelection, setValue])
|
||||
|
||||
const params = useQueryParams(["q", "order"])
|
||||
const { sales_channels, count } = useAdminSalesChannels(
|
||||
const { sales_channels, count, isLoading } = useSalesChannels(
|
||||
{ ...searchParams },
|
||||
{
|
||||
limit: PAGE_SIZE,
|
||||
offset: PAGE_SIZE * pageIndex,
|
||||
...params,
|
||||
},
|
||||
{
|
||||
keepPreviousData: true,
|
||||
placeholderData: keepPreviousData,
|
||||
}
|
||||
)
|
||||
|
||||
const columns = useColumns()
|
||||
const updater: OnChangeFn<RowSelectionState> = (fn) => {
|
||||
const state = typeof fn === "function" ? fn(rowSelection) : fn
|
||||
|
||||
const table = useReactTable({
|
||||
const ids = Object.keys(state)
|
||||
|
||||
setValue("sales_channel_ids", ids, {
|
||||
shouldDirty: true,
|
||||
shouldTouch: true,
|
||||
})
|
||||
|
||||
setRowSelection(state)
|
||||
}
|
||||
|
||||
const { table } = useDataTable({
|
||||
data: sales_channels ?? [],
|
||||
columns,
|
||||
pageCount: Math.ceil((count ?? 0) / PAGE_SIZE),
|
||||
state: {
|
||||
pagination,
|
||||
rowSelection,
|
||||
},
|
||||
onPaginationChange: setPagination,
|
||||
onRowSelectionChange: setRowSelection,
|
||||
getCoreRowModel: getCoreRowModel(),
|
||||
manualPagination: true,
|
||||
getRowId: (row) => row.id,
|
||||
count,
|
||||
enablePagination: true,
|
||||
enableRowSelection: (row) => {
|
||||
return !preSelected.includes(row.id)
|
||||
return !preSelected.includes(row.original.id!)
|
||||
},
|
||||
meta: {
|
||||
preSelected,
|
||||
getRowId: (row) => row.id,
|
||||
pageSize: PAGE_SIZE,
|
||||
rowSelection: {
|
||||
state: rowSelection,
|
||||
updater,
|
||||
},
|
||||
})
|
||||
|
||||
@@ -165,85 +132,26 @@ export const AddSalesChannelsToApiKeyForm = ({
|
||||
</Button>
|
||||
</div>
|
||||
</RouteFocusModal.Header>
|
||||
<RouteFocusModal.Body className="flex h-full w-full flex-col items-center divide-y overflow-y-auto">
|
||||
<div className="flex w-full items-center justify-between px-6 py-4">
|
||||
<div></div>
|
||||
<div className="flex items-center gap-x-2">
|
||||
<Query />
|
||||
<OrderBy keys={["title"]} />
|
||||
</div>
|
||||
</div>
|
||||
<div className="w-full flex-1 overflow-y-auto">
|
||||
<Table>
|
||||
<Table.Header className="border-t-0">
|
||||
{table.getHeaderGroups().map((headerGroup) => {
|
||||
return (
|
||||
<Table.Row
|
||||
key={headerGroup.id}
|
||||
className="[&_th:first-of-type]:w-[1%] [&_th:first-of-type]:whitespace-nowrap"
|
||||
>
|
||||
{headerGroup.headers.map((header) => {
|
||||
return (
|
||||
<Table.HeaderCell key={header.id}>
|
||||
{flexRender(
|
||||
header.column.columnDef.header,
|
||||
header.getContext()
|
||||
)}
|
||||
</Table.HeaderCell>
|
||||
)
|
||||
})}
|
||||
</Table.Row>
|
||||
)
|
||||
})}
|
||||
</Table.Header>
|
||||
<Table.Body className="border-b-0">
|
||||
{table.getRowModel().rows.map((row) => (
|
||||
<Table.Row
|
||||
key={row.id}
|
||||
className={clx(
|
||||
"transition-fg",
|
||||
{
|
||||
"bg-ui-bg-highlight hover:bg-ui-bg-highlight-hover":
|
||||
row.getIsSelected(),
|
||||
},
|
||||
{
|
||||
"bg-ui-bg-disabled hover:bg-ui-bg-disabled":
|
||||
preSelected.includes(row.original.id),
|
||||
}
|
||||
)}
|
||||
>
|
||||
{row.getVisibleCells().map((cell) => (
|
||||
<Table.Cell key={cell.id}>
|
||||
{flexRender(
|
||||
cell.column.columnDef.cell,
|
||||
cell.getContext()
|
||||
)}
|
||||
</Table.Cell>
|
||||
))}
|
||||
</Table.Row>
|
||||
))}
|
||||
</Table.Body>
|
||||
</Table>
|
||||
</div>
|
||||
<div className="w-full border-t">
|
||||
<LocalizedTablePagination
|
||||
canNextPage={table.getCanNextPage()}
|
||||
canPreviousPage={table.getCanPreviousPage()}
|
||||
nextPage={table.nextPage}
|
||||
previousPage={table.previousPage}
|
||||
count={count ?? 0}
|
||||
pageIndex={pageIndex}
|
||||
pageCount={table.getPageCount()}
|
||||
pageSize={PAGE_SIZE}
|
||||
/>
|
||||
</div>
|
||||
<RouteFocusModal.Body>
|
||||
<DataTable
|
||||
table={table}
|
||||
columns={columns}
|
||||
count={count}
|
||||
pageSize={PAGE_SIZE}
|
||||
pagination
|
||||
search
|
||||
isLoading={isLoading}
|
||||
queryObject={raw}
|
||||
orderBy={["name", "created_at", "updated_at"]}
|
||||
/>
|
||||
</RouteFocusModal.Body>
|
||||
</form>
|
||||
</RouteFocusModal.Form>
|
||||
)
|
||||
}
|
||||
|
||||
const columnHelper = createColumnHelper<SalesChannel>()
|
||||
const columnHelper =
|
||||
createColumnHelper<AdminSalesChannelResponse["sales_channel"]>()
|
||||
|
||||
const useColumns = () => {
|
||||
const { t } = useTranslation()
|
||||
@@ -266,28 +174,24 @@ const useColumns = () => {
|
||||
/>
|
||||
)
|
||||
},
|
||||
cell: ({ row, table }) => {
|
||||
const { preSelected } = table.options.meta as {
|
||||
preSelected: string[]
|
||||
}
|
||||
|
||||
const isAdded = preSelected.includes(row.original.id)
|
||||
const isSelected = row.getIsSelected() || isAdded
|
||||
cell: ({ row }) => {
|
||||
const isPreSelected = !row.getCanSelect()
|
||||
const isSelected = row.getIsSelected() || isPreSelected
|
||||
|
||||
const Component = (
|
||||
<Checkbox
|
||||
checked={isSelected}
|
||||
disabled={isAdded}
|
||||
disabled={isPreSelected}
|
||||
onCheckedChange={(value) => row.toggleSelected(!!value)}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
}}
|
||||
/>
|
||||
)
|
||||
|
||||
if (isAdded) {
|
||||
if (isPreSelected) {
|
||||
return (
|
||||
<Tooltip
|
||||
content={t("salesChannels.productAlreadyAdded")}
|
||||
side="right"
|
||||
>
|
||||
<Tooltip content={t("store.currencyAlreadyAdded")} side="right">
|
||||
{Component}
|
||||
</Tooltip>
|
||||
)
|
||||
|
||||
@@ -3,6 +3,7 @@ import { JsonViewSection } from "../../../components/common/json-view-section"
|
||||
import { useApiKey } from "../../../hooks/api/api-keys"
|
||||
import { ApiKeyGeneralSection } from "./components/api-key-general-section"
|
||||
import { apiKeyLoader } from "./loader"
|
||||
import { ApiKeySalesChannelSection } from "./components/api-key-sales-channel-section"
|
||||
|
||||
export const ApiKeyManagementDetail = () => {
|
||||
const initialData = useLoaderData() as Awaited<
|
||||
@@ -25,7 +26,7 @@ export const ApiKeyManagementDetail = () => {
|
||||
return (
|
||||
<div className="flex flex-col gap-y-2">
|
||||
<ApiKeyGeneralSection apiKey={api_key} />
|
||||
{/* <ApiKeySalesChannelSection apiKey={apiKey} /> */}
|
||||
<ApiKeySalesChannelSection apiKey={api_key} />
|
||||
<JsonViewSection data={api_key} />
|
||||
<Outlet />
|
||||
</div>
|
||||
|
||||
@@ -1,366 +1,254 @@
|
||||
// Api Key Sales Channel Endpoint is not part of v2
|
||||
import { PencilSquare, Trash } from "@medusajs/icons"
|
||||
import {
|
||||
Button,
|
||||
Checkbox,
|
||||
Container,
|
||||
Heading,
|
||||
StatusBadge,
|
||||
usePrompt,
|
||||
} from "@medusajs/ui"
|
||||
import { RowSelectionState, createColumnHelper } from "@tanstack/react-table"
|
||||
import {
|
||||
adminPublishableApiKeysKeys,
|
||||
useAdminCustomPost,
|
||||
useAdminRemovePublishableKeySalesChannelsBatch,
|
||||
} from "medusa-react"
|
||||
import { useMemo, useState } from "react"
|
||||
import { useTranslation } from "react-i18next"
|
||||
import { Link, useNavigate } from "react-router-dom"
|
||||
import { ActionMenu } from "../../../../../components/common/action-menu"
|
||||
import { useSalesChannels } from "../../../../../hooks/api/sales-channels"
|
||||
import { useSalesChannelTableQuery } from "../../../../../hooks/table/query/use-sales-channel-table-query"
|
||||
import { useDataTable } from "../../../../../hooks/use-data-table"
|
||||
import { DataTable } from "../../../../../components/table/data-table"
|
||||
import { keepPreviousData } from "@tanstack/react-query"
|
||||
import { AdminApiKeyResponse, AdminSalesChannelResponse } from "@medusajs/types"
|
||||
import { useBatchRemoveSalesChannelsFromApiKey } from "../../../../../hooks/api/api-keys"
|
||||
|
||||
// import { PencilSquare, Trash } from "@medusajs/icons"
|
||||
// import { SalesChannel } from "@medusajs/medusa"
|
||||
// import {
|
||||
// Button,
|
||||
// Checkbox,
|
||||
// CommandBar,
|
||||
// Container,
|
||||
// Heading,
|
||||
// StatusBadge,
|
||||
// Table,
|
||||
// clx,
|
||||
// usePrompt,
|
||||
// } from "@medusajs/ui"
|
||||
// import {
|
||||
// PaginationState,
|
||||
// RowSelectionState,
|
||||
// createColumnHelper,
|
||||
// flexRender,
|
||||
// getCoreRowModel,
|
||||
// useReactTable,
|
||||
// } from "@tanstack/react-table"
|
||||
// import {
|
||||
// adminPublishableApiKeysKeys,
|
||||
// useAdminCustomPost,
|
||||
// useAdminRemovePublishableKeySalesChannelsBatch,
|
||||
// } from "medusa-react"
|
||||
// import { useMemo, useState } from "react"
|
||||
// import { useTranslation } from "react-i18next"
|
||||
// import { Link, useNavigate } from "react-router-dom"
|
||||
// import { ActionMenu } from "../../../../../components/common/action-menu"
|
||||
// import {
|
||||
// NoRecords,
|
||||
// NoResults,
|
||||
// } from "../../../../../components/common/empty-table-content"
|
||||
// import { Query } from "../../../../../components/filtering/query"
|
||||
// import { LocalizedTablePagination } from "../../../../../components/localization/localized-table-pagination"
|
||||
// import { useQueryParams } from "../../../../../hooks/use-query-params"
|
||||
// import { ExtendedApiKeyDTO } from "../../../../../types/api-responses"
|
||||
// import { SalesChannelDTO } from "@medusajs/types"
|
||||
type ApiKeySalesChannelSectionProps = {
|
||||
apiKey: AdminApiKeyResponse["api_key"]
|
||||
}
|
||||
|
||||
// type ApiKeySalesChannelSectionProps = {
|
||||
// apiKey: ExtendedApiKeyDTO
|
||||
// }
|
||||
const PAGE_SIZE = 10
|
||||
|
||||
// const PAGE_SIZE = 10
|
||||
export const ApiKeySalesChannelSection = ({
|
||||
apiKey,
|
||||
}: ApiKeySalesChannelSectionProps) => {
|
||||
const [rowSelection, setRowSelection] = useState<RowSelectionState>({})
|
||||
const { t } = useTranslation()
|
||||
const prompt = usePrompt()
|
||||
|
||||
// export const ApiKeySalesChannelSection = ({
|
||||
// apiKey,
|
||||
// }: ApiKeySalesChannelSectionProps) => {
|
||||
// const { t } = useTranslation()
|
||||
// const navigate = useNavigate()
|
||||
// const prompt = usePrompt()
|
||||
const { raw, searchParams } = useSalesChannelTableQuery({
|
||||
pageSize: PAGE_SIZE,
|
||||
})
|
||||
|
||||
// const [{ pageIndex, pageSize }, setPagination] = useState<PaginationState>({
|
||||
// pageIndex: 0,
|
||||
// pageSize: PAGE_SIZE,
|
||||
// })
|
||||
const { sales_channels, count, isLoading } = useSalesChannels(
|
||||
{ ...searchParams, publishable_key_id: apiKey.id },
|
||||
{
|
||||
placeholderData: keepPreviousData,
|
||||
}
|
||||
)
|
||||
|
||||
// const pagination = useMemo(
|
||||
// () => ({
|
||||
// pageIndex,
|
||||
// pageSize,
|
||||
// }),
|
||||
// [pageIndex, pageSize]
|
||||
// )
|
||||
const columns = useColumns({ apiKey: apiKey.id })
|
||||
// const filters = useProductTableFilters(["sales_channel_id"])
|
||||
|
||||
// const [rowSelection, setRowSelection] = useState<RowSelectionState>({})
|
||||
const { table } = useDataTable({
|
||||
data: sales_channels ?? [],
|
||||
columns,
|
||||
count,
|
||||
enablePagination: true,
|
||||
enableRowSelection: true,
|
||||
getRowId: (row) => row.id,
|
||||
pageSize: PAGE_SIZE,
|
||||
rowSelection: {
|
||||
state: rowSelection,
|
||||
updater: setRowSelection,
|
||||
},
|
||||
})
|
||||
|
||||
// const params = useQueryParams(["q"])
|
||||
const { mutateAsync } = useBatchRemoveSalesChannelsFromApiKey(apiKey.id)
|
||||
|
||||
// const query = {
|
||||
// ...params,
|
||||
// fields: "id,*sales_channels",
|
||||
// }
|
||||
const handleRemove = async () => {
|
||||
const keys = Object.keys(rowSelection)
|
||||
|
||||
// const salesChannels = apiKey?.sales_channels
|
||||
// const count = salesChannels?.length || 0
|
||||
const res = await prompt({
|
||||
title: t("general.areYouSure"),
|
||||
description: t("apiKeyManagement.removeSalesChannelsWarning", {
|
||||
count: keys.length,
|
||||
}),
|
||||
confirmText: t("actions.continue"),
|
||||
cancelText: t("actions.cancel"),
|
||||
})
|
||||
|
||||
// const columns = useColumns()
|
||||
if (!res) {
|
||||
return
|
||||
}
|
||||
|
||||
// const table = useReactTable({
|
||||
// data: salesChannels ?? [],
|
||||
// columns,
|
||||
// pageCount: Math.ceil(count / PAGE_SIZE),
|
||||
// state: {
|
||||
// pagination,
|
||||
// rowSelection,
|
||||
// },
|
||||
// getRowId: (row) => row.id,
|
||||
// onPaginationChange: setPagination,
|
||||
// onRowSelectionChange: setRowSelection,
|
||||
// getCoreRowModel: getCoreRowModel(),
|
||||
// manualPagination: true,
|
||||
// meta: {
|
||||
// apiKey: apiKey.id,
|
||||
// },
|
||||
// })
|
||||
await mutateAsync(
|
||||
{
|
||||
sales_channel_ids: keys,
|
||||
},
|
||||
{
|
||||
onSuccess: () => {
|
||||
setRowSelection({})
|
||||
},
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
// const { mutateAsync } = useAdminCustomPost(
|
||||
// `/api-keys/${apiKey.id}/sales-channels/batch/remove`,
|
||||
// [adminPublishableApiKeysKeys.detailSalesChannels(apiKey.id)]
|
||||
// )
|
||||
return (
|
||||
<Container className="divide-y p-0">
|
||||
<div className="flex items-center justify-between px-6 py-4">
|
||||
<Heading level="h2">{t("salesChannels.domain")}</Heading>
|
||||
<Button variant="secondary" size="small" asChild>
|
||||
<Link to="add-sales-channels">{t("general.add")}</Link>
|
||||
</Button>
|
||||
</div>
|
||||
<DataTable
|
||||
table={table}
|
||||
columns={columns}
|
||||
count={count}
|
||||
pageSize={PAGE_SIZE}
|
||||
pagination
|
||||
search
|
||||
isLoading={isLoading}
|
||||
queryObject={raw}
|
||||
orderBy={["name", "created_at", "updated_at"]}
|
||||
commands={[
|
||||
{
|
||||
action: handleRemove,
|
||||
label: t("actions.remove"),
|
||||
shortcut: "r",
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</Container>
|
||||
)
|
||||
}
|
||||
|
||||
// const handleRemove = async () => {
|
||||
// const keys = Object.keys(rowSelection).filter((k) => rowSelection[k])
|
||||
const SalesChannelActions = ({
|
||||
salesChannel,
|
||||
apiKey,
|
||||
}: {
|
||||
salesChannel: AdminSalesChannelResponse["sales_channel"]
|
||||
apiKey: string
|
||||
}) => {
|
||||
const { t } = useTranslation()
|
||||
const prompt = usePrompt()
|
||||
|
||||
// const res = await prompt({
|
||||
// title: t("general.areYouSure"),
|
||||
// description: t("apiKeyManagement.removeSalesChannelsWarning", {
|
||||
// count: keys.length,
|
||||
// }),
|
||||
// confirmText: t("actions.continue"),
|
||||
// cancelText: t("actions.cancel"),
|
||||
// })
|
||||
const { mutateAsync } = useBatchRemoveSalesChannelsFromApiKey(apiKey)
|
||||
|
||||
// if (!res) {
|
||||
// return
|
||||
// }
|
||||
const handleDelete = async () => {
|
||||
const res = await prompt({
|
||||
title: t("general.areYouSure"),
|
||||
description: t("apiKeyManagement.removeSalesChannelWarning", {
|
||||
name: salesChannel.name,
|
||||
}),
|
||||
confirmText: t("actions.delete"),
|
||||
cancelText: t("actions.cancel"),
|
||||
})
|
||||
|
||||
// await mutateAsync(
|
||||
// {
|
||||
// sales_channel_ids: keys,
|
||||
// },
|
||||
// {
|
||||
// onSuccess: () => {
|
||||
// setRowSelection({})
|
||||
// },
|
||||
// }
|
||||
// )
|
||||
// }
|
||||
if (!res) {
|
||||
return
|
||||
}
|
||||
|
||||
// const noRecords = !salesChannels?.length && !params.q
|
||||
await mutateAsync({
|
||||
sales_channel_ids: [salesChannel.id],
|
||||
})
|
||||
}
|
||||
|
||||
// return (
|
||||
// <Container className="divide-y p-0">
|
||||
// <div className="flex items-center justify-between px-6 py-4">
|
||||
// <Heading level="h2">{t("salesChannels.domain")}</Heading>
|
||||
// <Button variant="secondary" size="small" asChild>
|
||||
// <Link to="add-sales-channels">{t("general.add")}</Link>
|
||||
// </Button>
|
||||
// </div>
|
||||
// {!noRecords && (
|
||||
// <div className="flex items-center justify-between px-6 py-4">
|
||||
// <div></div>
|
||||
// <div className="flex items-center gap-x-2">
|
||||
// <Query />
|
||||
// </div>
|
||||
// </div>
|
||||
// )}
|
||||
// {noRecords ? (
|
||||
// <NoRecords />
|
||||
// ) : (
|
||||
// <div>
|
||||
// {salesChannels?.length !== 0 ? (
|
||||
// <Table>
|
||||
// <Table.Header className="border-t-0">
|
||||
// {table.getHeaderGroups().map((headerGroup) => {
|
||||
// return (
|
||||
// <Table.Row
|
||||
// key={headerGroup.id}
|
||||
// className="[&_th:first-of-type]:w-[1%] [&_th:first-of-type]:whitespace-nowrap [&_th:last-of-type]:w-[1%] [&_th:last-of-type]:whitespace-nowrap [&_th]:w-1/3"
|
||||
// >
|
||||
// {headerGroup.headers.map((header) => {
|
||||
// return (
|
||||
// <Table.HeaderCell key={header.id}>
|
||||
// {flexRender(
|
||||
// header.column.columnDef.header,
|
||||
// header.getContext()
|
||||
// )}
|
||||
// </Table.HeaderCell>
|
||||
// )
|
||||
// })}
|
||||
// </Table.Row>
|
||||
// )
|
||||
// })}
|
||||
// </Table.Header>
|
||||
// <Table.Body className="border-b-0">
|
||||
// {table.getRowModel().rows.map((row) => (
|
||||
// <Table.Row
|
||||
// key={row.id}
|
||||
// className={clx(
|
||||
// "transition-fg cursor-pointer [&_td:last-of-type]:w-[1%] [&_td:last-of-type]:whitespace-nowrap",
|
||||
// {
|
||||
// "bg-ui-bg-highlight hover:bg-ui-bg-highlight-hover":
|
||||
// row.getIsSelected(),
|
||||
// }
|
||||
// )}
|
||||
// onClick={() =>
|
||||
// navigate(`/settings/sales-channels/${row.original.id}`)
|
||||
// }
|
||||
// >
|
||||
// {row.getVisibleCells().map((cell) => (
|
||||
// <Table.Cell key={cell.id}>
|
||||
// {flexRender(
|
||||
// cell.column.columnDef.cell,
|
||||
// cell.getContext()
|
||||
// )}
|
||||
// </Table.Cell>
|
||||
// ))}
|
||||
// </Table.Row>
|
||||
// ))}
|
||||
// </Table.Body>
|
||||
// </Table>
|
||||
// ) : (
|
||||
// <NoResults />
|
||||
// )}
|
||||
// <LocalizedTablePagination
|
||||
// canNextPage={table.getCanNextPage()}
|
||||
// canPreviousPage={table.getCanPreviousPage()}
|
||||
// nextPage={table.nextPage}
|
||||
// previousPage={table.previousPage}
|
||||
// count={count ?? 0}
|
||||
// pageIndex={pageIndex}
|
||||
// pageCount={table.getPageCount()}
|
||||
// pageSize={PAGE_SIZE}
|
||||
// />
|
||||
// <CommandBar open={!!Object.keys(rowSelection).length}>
|
||||
// <CommandBar.Bar>
|
||||
// <CommandBar.Value>
|
||||
// {t("general.countSelected", {
|
||||
// count: Object.keys(rowSelection).length,
|
||||
// })}
|
||||
// </CommandBar.Value>
|
||||
// <CommandBar.Seperator />
|
||||
// <CommandBar.Command
|
||||
// action={handleRemove}
|
||||
// shortcut="r"
|
||||
// label={t("actions.remove")}
|
||||
// />
|
||||
// </CommandBar.Bar>
|
||||
// </CommandBar>
|
||||
// </div>
|
||||
// )}
|
||||
// </Container>
|
||||
// )
|
||||
// }
|
||||
return (
|
||||
<ActionMenu
|
||||
groups={[
|
||||
{
|
||||
actions: [
|
||||
{
|
||||
icon: <PencilSquare />,
|
||||
label: t("actions.edit"),
|
||||
to: `/settings/sales-channels/${salesChannel.id}/edit`,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
actions: [
|
||||
{
|
||||
icon: <Trash />,
|
||||
label: t("actions.delete"),
|
||||
onClick: handleDelete,
|
||||
},
|
||||
],
|
||||
},
|
||||
]}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
// const SalesChannelActions = ({
|
||||
// salesChannel,
|
||||
// apiKey,
|
||||
// }: {
|
||||
// salesChannel: SalesChannelDTO
|
||||
// apiKey: string
|
||||
// }) => {
|
||||
// const { t } = useTranslation()
|
||||
// const prompt = usePrompt()
|
||||
const columnHelper =
|
||||
createColumnHelper<AdminSalesChannelResponse["sales_channel"]>()
|
||||
|
||||
// const { mutateAsync } = useAdminRemovePublishableKeySalesChannelsBatch(apiKey)
|
||||
const useColumns = ({ apiKey }: { apiKey: string }) => {
|
||||
const { t } = useTranslation()
|
||||
|
||||
// const handleDelete = async () => {
|
||||
// const res = await prompt({
|
||||
// title: t("general.areYouSure"),
|
||||
// description: t("apiKeyManagement.removeSalesChannelWarning"),
|
||||
// confirmText: t("actions.delete"),
|
||||
// cancelText: t("actions.cancel"),
|
||||
// })
|
||||
|
||||
// if (!res) {
|
||||
// return
|
||||
// }
|
||||
|
||||
// await mutateAsync({
|
||||
// sales_channel_ids: [{ id: salesChannel.id }],
|
||||
// })
|
||||
// }
|
||||
|
||||
// return (
|
||||
// <ActionMenu
|
||||
// groups={[
|
||||
// {
|
||||
// actions: [
|
||||
// {
|
||||
// icon: <PencilSquare />,
|
||||
// label: t("actions.edit"),
|
||||
// to: `/settings/sales-channels/${salesChannel.id}/edit`,
|
||||
// },
|
||||
// ],
|
||||
// },
|
||||
// {
|
||||
// actions: [
|
||||
// {
|
||||
// icon: <Trash />,
|
||||
// label: t("actions.delete"),
|
||||
// onClick: handleDelete,
|
||||
// },
|
||||
// ],
|
||||
// },
|
||||
// ]}
|
||||
// />
|
||||
// )
|
||||
// }
|
||||
|
||||
// const columnHelper = createColumnHelper<SalesChannel>()
|
||||
|
||||
// const useColumns = () => {
|
||||
// const { t } = useTranslation()
|
||||
|
||||
// return useMemo(
|
||||
// () => [
|
||||
// columnHelper.display({
|
||||
// id: "select",
|
||||
// header: ({ table }) => {
|
||||
// return (
|
||||
// <Checkbox
|
||||
// checked={
|
||||
// table.getIsSomePageRowsSelected()
|
||||
// ? "indeterminate"
|
||||
// : table.getIsAllPageRowsSelected()
|
||||
// }
|
||||
// onCheckedChange={(value) =>
|
||||
// table.toggleAllPageRowsSelected(!!value)
|
||||
// }
|
||||
// />
|
||||
// )
|
||||
// },
|
||||
// cell: ({ row }) => {
|
||||
// return (
|
||||
// <Checkbox
|
||||
// checked={row.getIsSelected()}
|
||||
// onCheckedChange={(value) => row.toggleSelected(!!value)}
|
||||
// onClick={(e) => {
|
||||
// e.stopPropagation()
|
||||
// }}
|
||||
// />
|
||||
// )
|
||||
// },
|
||||
// }),
|
||||
// columnHelper.accessor("name", {
|
||||
// header: t("fields.name"),
|
||||
// cell: ({ getValue }) => getValue(),
|
||||
// }),
|
||||
// columnHelper.accessor("description", {
|
||||
// header: t("fields.description"),
|
||||
// cell: ({ getValue }) => getValue(),
|
||||
// }),
|
||||
// columnHelper.accessor("is_disabled", {
|
||||
// header: t("fields.status"),
|
||||
// cell: ({ getValue }) => {
|
||||
// const value = getValue()
|
||||
// return (
|
||||
// <div>
|
||||
// <StatusBadge color={value ? "grey" : "green"}>
|
||||
// {value ? t("general.disabled") : t("general.enabled")}
|
||||
// </StatusBadge>
|
||||
// </div>
|
||||
// )
|
||||
// },
|
||||
// }),
|
||||
// columnHelper.display({
|
||||
// id: "actions",
|
||||
// cell: ({ row, table }) => {
|
||||
// const { apiKey } = table.options.meta as {
|
||||
// apiKey: string
|
||||
// }
|
||||
|
||||
// return (
|
||||
// <SalesChannelActions salesChannel={row.original} apiKey={apiKey} />
|
||||
// )
|
||||
// },
|
||||
// }),
|
||||
// ],
|
||||
// [t]
|
||||
// )
|
||||
// }
|
||||
return useMemo(
|
||||
() => [
|
||||
columnHelper.display({
|
||||
id: "select",
|
||||
header: ({ table }) => {
|
||||
return (
|
||||
<Checkbox
|
||||
checked={
|
||||
table.getIsSomePageRowsSelected()
|
||||
? "indeterminate"
|
||||
: table.getIsAllPageRowsSelected()
|
||||
}
|
||||
onCheckedChange={(value) =>
|
||||
table.toggleAllPageRowsSelected(!!value)
|
||||
}
|
||||
/>
|
||||
)
|
||||
},
|
||||
cell: ({ row }) => {
|
||||
return (
|
||||
<Checkbox
|
||||
checked={row.getIsSelected()}
|
||||
onCheckedChange={(value) => row.toggleSelected(!!value)}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
}}
|
||||
/>
|
||||
)
|
||||
},
|
||||
}),
|
||||
columnHelper.accessor("name", {
|
||||
header: t("fields.name"),
|
||||
cell: ({ getValue }) => getValue(),
|
||||
}),
|
||||
columnHelper.accessor("description", {
|
||||
header: t("fields.description"),
|
||||
cell: ({ getValue }) => getValue(),
|
||||
}),
|
||||
columnHelper.accessor("is_disabled", {
|
||||
header: t("fields.status"),
|
||||
cell: ({ getValue }) => {
|
||||
const value = getValue()
|
||||
return (
|
||||
<div>
|
||||
<StatusBadge color={value ? "grey" : "green"}>
|
||||
{value ? t("general.disabled") : t("general.enabled")}
|
||||
</StatusBadge>
|
||||
</div>
|
||||
)
|
||||
},
|
||||
}),
|
||||
columnHelper.display({
|
||||
id: "actions",
|
||||
cell: ({ row, table }) => {
|
||||
return (
|
||||
<SalesChannelActions salesChannel={row.original} apiKey={apiKey} />
|
||||
)
|
||||
},
|
||||
}),
|
||||
],
|
||||
[t]
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { LoaderFunctionArgs } from "react-router-dom"
|
||||
|
||||
import { AdminApiKeyResponse } from "@medusajs/types"
|
||||
import { apiKeysQueryKeys } from "../../../hooks/api/api-keys"
|
||||
import { client } from "../../../lib/client"
|
||||
import { queryClient } from "../../../lib/medusa"
|
||||
import { ApiKeyRes } from "../../../types/api-responses"
|
||||
|
||||
const apiKeyDetailQuery = (id: string) => ({
|
||||
queryKey: apiKeysQueryKeys.detail(id),
|
||||
@@ -15,7 +15,7 @@ export const apiKeyLoader = async ({ params }: LoaderFunctionArgs) => {
|
||||
const query = apiKeyDetailQuery(id!)
|
||||
|
||||
return (
|
||||
queryClient.getQueryData<ApiKeyRes>(query.queryKey) ??
|
||||
queryClient.getQueryData<AdminApiKeyResponse>(query.queryKey) ??
|
||||
(await queryClient.fetchQuery(query))
|
||||
)
|
||||
}
|
||||
|
||||
@@ -9,13 +9,16 @@ import {
|
||||
} from "medusa-react"
|
||||
import { useMemo } from "react"
|
||||
import { useTranslation } from "react-i18next"
|
||||
|
||||
import { ApiKeyDTO } from "@medusajs/types"
|
||||
import { AdminApiKeyResponse } from "@medusajs/types"
|
||||
import { ActionMenu } from "../../../../../components/common/action-menu"
|
||||
import { DateCell } from "../../../../../components/table/table-cells/common/date-cell"
|
||||
import { StatusCell } from "../../../../../components/table/table-cells/common/status-cell"
|
||||
import {
|
||||
useDeleteApiKey,
|
||||
useRevokeApiKey,
|
||||
} from "../../../../../hooks/api/api-keys"
|
||||
|
||||
const columnHelper = createColumnHelper<ApiKeyDTO>()
|
||||
const columnHelper = createColumnHelper<AdminApiKeyResponse["api_key"]>()
|
||||
|
||||
export const useApiKeyManagementTableColumns = () => {
|
||||
const { t } = useTranslation()
|
||||
@@ -83,21 +86,9 @@ export const useApiKeyManagementTableColumns = () => {
|
||||
)
|
||||
}
|
||||
|
||||
const ApiKeyActions = ({ apiKey }: { apiKey: PublishableApiKey }) => {
|
||||
const { mutateAsync: revokeAsync } = useAdminCustomPost(
|
||||
`/api-keys/${apiKey.id}/revoke`,
|
||||
[
|
||||
adminPublishableApiKeysKeys.lists(),
|
||||
adminPublishableApiKeysKeys.detail(apiKey.id),
|
||||
]
|
||||
)
|
||||
const { mutateAsync: deleteAsync } = useAdminCustomDelete(
|
||||
`/api-keys/${apiKey.id}`,
|
||||
[
|
||||
adminPublishableApiKeysKeys.lists(),
|
||||
adminPublishableApiKeysKeys.detail(apiKey.id),
|
||||
]
|
||||
)
|
||||
export const ApiKeyActions = ({ apiKey }: { apiKey: PublishableApiKey }) => {
|
||||
const { mutateAsync: revokeAsync } = useRevokeApiKey(apiKey.id)
|
||||
const { mutateAsync: deleteAsync } = useDeleteApiKey(apiKey.id)
|
||||
|
||||
const { t } = useTranslation()
|
||||
const prompt = usePrompt()
|
||||
@@ -133,7 +124,7 @@ const ApiKeyActions = ({ apiKey }: { apiKey: PublishableApiKey }) => {
|
||||
return
|
||||
}
|
||||
|
||||
await revokeAsync({})
|
||||
await revokeAsync(undefined)
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { adminProductKeys } from "medusa-react"
|
||||
import { LoaderFunctionArgs } from "react-router-dom"
|
||||
|
||||
import { AdminSalesChannelResponse } from "@medusajs/types"
|
||||
import { client } from "../../../lib/client"
|
||||
import { queryClient } from "../../../lib/medusa"
|
||||
import { SalesChannelRes } from "../../../types/api-responses"
|
||||
|
||||
const salesChannelDetailQuery = (id: string) => ({
|
||||
queryKey: adminProductKeys.detail(id),
|
||||
@@ -15,7 +15,7 @@ export const salesChannelLoader = async ({ params }: LoaderFunctionArgs) => {
|
||||
const query = salesChannelDetailQuery(id!)
|
||||
|
||||
return (
|
||||
queryClient.getQueryData<SalesChannelRes>(query.queryKey) ??
|
||||
queryClient.getQueryData<AdminSalesChannelResponse>(query.queryKey) ??
|
||||
(await queryClient.fetchQuery(query))
|
||||
)
|
||||
}
|
||||
|
||||
32
packages/types/src/http/api-key/admin/api-key.ts
Normal file
32
packages/types/src/http/api-key/admin/api-key.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
import { ApiKeyType } from "../../../api-key"
|
||||
import { PaginatedResponse } from "../../../common"
|
||||
|
||||
/**
|
||||
* @experimental
|
||||
*/
|
||||
interface ApiKeyResponse {
|
||||
id: string
|
||||
token: string
|
||||
redacted: string
|
||||
title: string
|
||||
type: ApiKeyType
|
||||
last_used_at: Date | null
|
||||
created_by: string
|
||||
created_at: Date
|
||||
revoked_by: string | null
|
||||
revoked_at: Date | null
|
||||
}
|
||||
|
||||
/**
|
||||
* @experimental
|
||||
*/
|
||||
export interface AdminApiKeyResponse {
|
||||
api_key: ApiKeyResponse
|
||||
}
|
||||
|
||||
/**
|
||||
* @experimental
|
||||
*/
|
||||
export interface AdminApiKeyListResponse extends PaginatedResponse {
|
||||
api_keys: ApiKeyResponse[]
|
||||
}
|
||||
1
packages/types/src/http/api-key/admin/index.ts
Normal file
1
packages/types/src/http/api-key/admin/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from "./api-key"
|
||||
1
packages/types/src/http/api-key/index.ts
Normal file
1
packages/types/src/http/api-key/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from "./admin"
|
||||
1
packages/types/src/http/common/index.ts
Normal file
1
packages/types/src/http/common/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from "./paginated-response"
|
||||
5
packages/types/src/http/common/paginated-response.ts
Normal file
5
packages/types/src/http/common/paginated-response.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
export interface PaginatedResponse {
|
||||
limit: number
|
||||
offset: number
|
||||
count: number
|
||||
}
|
||||
@@ -1,2 +1,4 @@
|
||||
export * from "./stock-locations"
|
||||
export * from "./api-key"
|
||||
export * from "./fulfillment"
|
||||
export * from "./sales-channel"
|
||||
export * from "./stock-locations"
|
||||
|
||||
1
packages/types/src/http/sales-channel/admin/index.ts
Normal file
1
packages/types/src/http/sales-channel/admin/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from "./sales-channel"
|
||||
26
packages/types/src/http/sales-channel/admin/sales-channel.ts
Normal file
26
packages/types/src/http/sales-channel/admin/sales-channel.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
import { PaginatedResponse } from "../../common"
|
||||
|
||||
/**
|
||||
* @experimental
|
||||
*/
|
||||
interface SalesChannelResponse {
|
||||
id: string
|
||||
name: string
|
||||
description: string | null
|
||||
is_disabled: boolean
|
||||
metadata: Record<string, unknown> | null
|
||||
}
|
||||
|
||||
/**
|
||||
* @experimental
|
||||
*/
|
||||
export interface AdminSalesChannelListResponse extends PaginatedResponse {
|
||||
sales_channels: SalesChannelResponse[]
|
||||
}
|
||||
|
||||
/**
|
||||
* @experimental
|
||||
*/
|
||||
export interface AdminSalesChannelResponse {
|
||||
sales_channel: SalesChannelResponse
|
||||
}
|
||||
1
packages/types/src/http/sales-channel/index.ts
Normal file
1
packages/types/src/http/sales-channel/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from "./admin"
|
||||
Reference in New Issue
Block a user