mirror of https://github.com/buster-so/buster.git
Refactor sharing request types and enhance asset icon mapping
- Updated sharing request types to use SharePermissionsUpdateRequest for clarity across collections, dashboards, and metrics. - Enhanced asset icon mapping to include additional asset types for better UI representation. - Improved error handling in the MetricDataTruncatedWarning component to provide user feedback during download failures.
This commit is contained in:
parent
a133653ccc
commit
895e28f8d4
|
@ -234,7 +234,7 @@ export const useUpdateCollectionShare = () => {
|
|||
return create(previousData, (draft) => {
|
||||
draft.individual_permissions = (
|
||||
draft.individual_permissions?.map((t) => {
|
||||
const found = params.users?.find((v) => v.email === t.email);
|
||||
const found = params.users?.find((v: { email: string; role: string }) => v.email === t.email);
|
||||
if (found) return { ...t, ...found };
|
||||
return t;
|
||||
}) || []
|
||||
|
|
|
@ -2,7 +2,7 @@ import type { ShareAssetType } from '@buster/server-shared/share';
|
|||
import type { BusterCollection, BusterCollectionListItem } from '@/api/asset_interfaces/collection';
|
||||
import mainApi from '@/api/buster_rest/instances';
|
||||
import type { SharePostRequest } from '@buster/server-shared/share';
|
||||
import type { ShareDeleteRequest, ShareUpdateRequest } from '@buster/server-shared/share';
|
||||
import type { ShareDeleteRequest, SharePermissionsUpdateRequest } from '@buster/server-shared/share';
|
||||
|
||||
export const collectionsGetList = async (params: {
|
||||
/** Current page number (1-based indexing) */
|
||||
|
@ -91,7 +91,7 @@ export const updateCollectionShare = async ({
|
|||
id
|
||||
}: {
|
||||
id: string;
|
||||
params: ShareUpdateRequest;
|
||||
params: SharePermissionsUpdateRequest;
|
||||
}) => {
|
||||
return mainApi
|
||||
.put<BusterCollection>(`/collections/${id}/sharing`, params)
|
||||
|
|
|
@ -6,7 +6,7 @@ import type {
|
|||
import type {
|
||||
SharePostRequest,
|
||||
ShareDeleteRequest,
|
||||
ShareUpdateRequest
|
||||
SharePermissionsUpdateRequest
|
||||
} from '@buster/server-shared/share';
|
||||
import mainApi from '@/api/buster_rest/instances';
|
||||
import { serverFetch } from '@/api/createServerInstance';
|
||||
|
@ -103,7 +103,7 @@ export const updateDashboardShare = async ({
|
|||
id
|
||||
}: {
|
||||
id: string;
|
||||
params: ShareUpdateRequest;
|
||||
params: SharePermissionsUpdateRequest;
|
||||
}) => {
|
||||
return mainApi
|
||||
.put<BusterDashboardResponse>(`/dashboards/${id}/sharing`, params)
|
||||
|
|
|
@ -17,7 +17,7 @@ import type {
|
|||
ShareUpdateResponse,
|
||||
MetricDownloadResponse
|
||||
} from '@buster/server-shared/metrics';
|
||||
import type { ShareDeleteRequest, ShareUpdateRequest } from '@buster/server-shared/share';
|
||||
import type { ShareDeleteRequest, SharePermissionsUpdateRequest } from '@buster/server-shared/share';
|
||||
import { serverFetch } from '@/api/createServerInstance';
|
||||
import { mainApi, mainApiV2 } from '../instances';
|
||||
import { SharePostRequest } from '@buster/server-shared/share';
|
||||
|
@ -99,7 +99,7 @@ export const updateMetricShare = async ({
|
|||
id
|
||||
}: {
|
||||
id: string;
|
||||
params: ShareUpdateRequest;
|
||||
params: SharePermissionsUpdateRequest;
|
||||
}) => {
|
||||
return mainApi
|
||||
.put<ShareUpdateResponse>(`/metric_files/${id}/sharing`, params)
|
||||
|
|
|
@ -25,15 +25,26 @@ export const ASSET_ICONS = {
|
|||
export const assetTypeToIcon = (assetType: ShareAssetType) => {
|
||||
switch (assetType) {
|
||||
case 'metric':
|
||||
case 'metric_file':
|
||||
return ASSET_ICONS.metrics;
|
||||
case 'dashboard':
|
||||
case 'dashboard_file':
|
||||
return ASSET_ICONS.dashboards;
|
||||
case 'collection':
|
||||
case 'collection_file':
|
||||
return ASSET_ICONS.collections;
|
||||
case 'chat':
|
||||
case 'thread':
|
||||
return ASSET_ICONS.chats;
|
||||
case 'report':
|
||||
return ASSET_ICONS.reports;
|
||||
case 'data_source':
|
||||
case 'filter':
|
||||
case 'dataset':
|
||||
case 'tool':
|
||||
case 'source':
|
||||
case 'dataset_permission':
|
||||
return ASSET_ICONS.table;
|
||||
default: {
|
||||
const _result: never = assetType;
|
||||
return ASSET_ICONS.metrics;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import React, { useState } from 'react';
|
||||
import { Text } from '@/components/ui/typography';
|
||||
import { Button } from '@/components/ui/buttons';
|
||||
import { Download4 } from '@/components/ui/icons';
|
||||
import { Download4, CircleWarning } from '@/components/ui/icons';
|
||||
import { cn } from '@/lib/classMerge';
|
||||
import { downloadMetricFile } from '@/api/buster_rest/metrics/requests';
|
||||
|
||||
|
@ -15,21 +15,30 @@ export const MetricDataTruncatedWarning: React.FC<MetricDataTruncatedWarningProp
|
|||
metricId
|
||||
}) => {
|
||||
const [isDownloading, setIsDownloading] = useState(false);
|
||||
const [hasError, setHasError] = useState(false);
|
||||
|
||||
const handleDownload = async () => {
|
||||
try {
|
||||
setIsDownloading(true);
|
||||
setHasError(false);
|
||||
|
||||
// Call the API to get the download URL
|
||||
const response = await downloadMetricFile(metricId);
|
||||
// Create a timeout promise that rejects after 3 minutes
|
||||
const timeoutPromise = new Promise((_, reject) => {
|
||||
setTimeout(() => reject(new Error('Download timeout')), 3 * 60 * 1000); // 3 minutes
|
||||
});
|
||||
|
||||
// Race between the API call and the timeout
|
||||
const response = await Promise.race([
|
||||
downloadMetricFile(metricId),
|
||||
timeoutPromise
|
||||
]) as Awaited<ReturnType<typeof downloadMetricFile>>;
|
||||
|
||||
// Simply navigate to the download URL
|
||||
// The response-content-disposition header will force a download
|
||||
window.location.href = response.downloadUrl;
|
||||
|
||||
} catch (error) {
|
||||
console.error('Failed to download metric file:', error);
|
||||
// You might want to show an error toast here
|
||||
setHasError(true);
|
||||
} finally {
|
||||
// Add a small delay before removing loading state since download happens async
|
||||
setTimeout(() => {
|
||||
|
@ -40,21 +49,30 @@ export const MetricDataTruncatedWarning: React.FC<MetricDataTruncatedWarningProp
|
|||
|
||||
return (
|
||||
<div
|
||||
className={cn('bg-background flex items-center justify-between rounded border p-4 shadow', className)}>
|
||||
className={cn(
|
||||
'bg-background flex items-center justify-between rounded border p-4 shadow',
|
||||
hasError && 'border-red-500',
|
||||
className
|
||||
)}>
|
||||
<div className="flex flex-col space-y-1">
|
||||
<Text className="font-medium">This request returned more than 5,000 records</Text>
|
||||
<Text size="xs" variant="secondary">
|
||||
To see all records, you'll need to download the results.
|
||||
<Text className="font-medium">
|
||||
{hasError
|
||||
? 'Download failed'
|
||||
: 'This request returned more than 5,000 records'}
|
||||
</Text>
|
||||
<Text size="xs" variant={hasError ? 'danger' : 'secondary'}>
|
||||
{hasError
|
||||
? 'The download took too long or encountered an error. Please try again.'
|
||||
: 'To see all records, you\'ll need to download the results.'}
|
||||
</Text>
|
||||
</div>
|
||||
<Button
|
||||
onClick={handleDownload}
|
||||
loading={isDownloading}
|
||||
variant="default"
|
||||
variant={hasError ? 'danger' : 'default'}
|
||||
className="ml-4"
|
||||
prefix={<Download4 />}
|
||||
>
|
||||
Download
|
||||
prefix={hasError ? <CircleWarning /> : <Download4 />}>
|
||||
{hasError ? 'Try Again' : 'Download'}
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
|
|
Loading…
Reference in New Issue