fixes of broken fucntions
This commit is contained in:
@@ -195,6 +195,26 @@ class AccountModelViewSet(viewsets.ModelViewSet):
|
|||||||
request=request
|
request=request
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def list(self, request, *args, **kwargs):
|
||||||
|
"""
|
||||||
|
Override list to return unified format
|
||||||
|
"""
|
||||||
|
queryset = self.filter_queryset(self.get_queryset())
|
||||||
|
|
||||||
|
# Check if pagination is enabled
|
||||||
|
page = self.paginate_queryset(queryset)
|
||||||
|
if page is not None:
|
||||||
|
serializer = self.get_serializer(page, many=True)
|
||||||
|
# Use paginator's get_paginated_response which already returns unified format
|
||||||
|
return self.get_paginated_response(serializer.data)
|
||||||
|
|
||||||
|
# No pagination - return all results in unified format
|
||||||
|
serializer = self.get_serializer(queryset, many=True)
|
||||||
|
return success_response(
|
||||||
|
data=serializer.data,
|
||||||
|
request=request
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class SiteSectorModelViewSet(AccountModelViewSet):
|
class SiteSectorModelViewSet(AccountModelViewSet):
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ from igny8_core.api.base import SiteSectorModelViewSet
|
|||||||
from igny8_core.api.pagination import CustomPageNumberPagination
|
from igny8_core.api.pagination import CustomPageNumberPagination
|
||||||
from igny8_core.api.response import success_response, error_response
|
from igny8_core.api.response import success_response, error_response
|
||||||
from igny8_core.api.throttles import DebugScopedRateThrottle
|
from igny8_core.api.throttles import DebugScopedRateThrottle
|
||||||
|
from igny8_core.api.permissions import IsAuthenticatedAndActive, IsViewerOrAbove, IsEditorOrAbove
|
||||||
from .models import Keywords, Clusters, ContentIdeas
|
from .models import Keywords, Clusters, ContentIdeas
|
||||||
from .serializers import KeywordSerializer, ContentIdeasSerializer
|
from .serializers import KeywordSerializer, ContentIdeasSerializer
|
||||||
from .cluster_serializers import ClusterSerializer
|
from .cluster_serializers import ClusterSerializer
|
||||||
@@ -25,7 +26,7 @@ class KeywordViewSet(SiteSectorModelViewSet):
|
|||||||
"""
|
"""
|
||||||
queryset = Keywords.objects.all()
|
queryset = Keywords.objects.all()
|
||||||
serializer_class = KeywordSerializer
|
serializer_class = KeywordSerializer
|
||||||
permission_classes = [] # Allow any for now
|
permission_classes = [IsAuthenticatedAndActive, IsViewerOrAbove]
|
||||||
pagination_class = CustomPageNumberPagination # Explicitly use custom pagination
|
pagination_class = CustomPageNumberPagination # Explicitly use custom pagination
|
||||||
throttle_scope = 'planner'
|
throttle_scope = 'planner'
|
||||||
throttle_classes = [DebugScopedRateThrottle]
|
throttle_classes = [DebugScopedRateThrottle]
|
||||||
@@ -668,6 +669,7 @@ class ClusterViewSet(SiteSectorModelViewSet):
|
|||||||
"""
|
"""
|
||||||
queryset = Clusters.objects.all()
|
queryset = Clusters.objects.all()
|
||||||
serializer_class = ClusterSerializer
|
serializer_class = ClusterSerializer
|
||||||
|
permission_classes = [IsAuthenticatedAndActive, IsViewerOrAbove]
|
||||||
pagination_class = CustomPageNumberPagination # Explicitly use custom pagination
|
pagination_class = CustomPageNumberPagination # Explicitly use custom pagination
|
||||||
throttle_scope = 'planner'
|
throttle_scope = 'planner'
|
||||||
throttle_classes = [DebugScopedRateThrottle]
|
throttle_classes = [DebugScopedRateThrottle]
|
||||||
@@ -957,6 +959,7 @@ class ContentIdeasViewSet(SiteSectorModelViewSet):
|
|||||||
"""
|
"""
|
||||||
queryset = ContentIdeas.objects.all()
|
queryset = ContentIdeas.objects.all()
|
||||||
serializer_class = ContentIdeasSerializer
|
serializer_class = ContentIdeasSerializer
|
||||||
|
permission_classes = [IsAuthenticatedAndActive, IsViewerOrAbove]
|
||||||
pagination_class = CustomPageNumberPagination
|
pagination_class = CustomPageNumberPagination
|
||||||
throttle_scope = 'planner'
|
throttle_scope = 'planner'
|
||||||
throttle_classes = [DebugScopedRateThrottle] # Explicitly use custom pagination
|
throttle_classes = [DebugScopedRateThrottle] # Explicitly use custom pagination
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ from django.db import transaction
|
|||||||
from igny8_core.api.base import AccountModelViewSet
|
from igny8_core.api.base import AccountModelViewSet
|
||||||
from igny8_core.api.response import success_response, error_response
|
from igny8_core.api.response import success_response, error_response
|
||||||
from igny8_core.api.throttles import DebugScopedRateThrottle
|
from igny8_core.api.throttles import DebugScopedRateThrottle
|
||||||
|
from igny8_core.api.permissions import IsAuthenticatedAndActive, IsAdminOrOwner
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
@@ -21,7 +22,7 @@ class IntegrationSettingsViewSet(viewsets.ViewSet):
|
|||||||
Following reference plugin pattern: WordPress uses update_option() for igny8_api_settings
|
Following reference plugin pattern: WordPress uses update_option() for igny8_api_settings
|
||||||
We store in IntegrationSettings model with account isolation
|
We store in IntegrationSettings model with account isolation
|
||||||
"""
|
"""
|
||||||
permission_classes = [] # Allow any for now
|
permission_classes = [IsAuthenticatedAndActive, IsAdminOrOwner]
|
||||||
|
|
||||||
throttle_scope = 'system_admin'
|
throttle_scope = 'system_admin'
|
||||||
throttle_classes = [DebugScopedRateThrottle]
|
throttle_classes = [DebugScopedRateThrottle]
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ from django.utils import timezone
|
|||||||
from django_filters.rest_framework import DjangoFilterBackend
|
from django_filters.rest_framework import DjangoFilterBackend
|
||||||
from igny8_core.api.base import AccountModelViewSet
|
from igny8_core.api.base import AccountModelViewSet
|
||||||
from igny8_core.api.response import success_response, error_response
|
from igny8_core.api.response import success_response, error_response
|
||||||
from igny8_core.api.permissions import IsEditorOrAbove
|
from igny8_core.api.permissions import IsEditorOrAbove, IsAuthenticatedAndActive, IsViewerOrAbove
|
||||||
from igny8_core.api.throttles import DebugScopedRateThrottle
|
from igny8_core.api.throttles import DebugScopedRateThrottle
|
||||||
from igny8_core.api.pagination import CustomPageNumberPagination
|
from igny8_core.api.pagination import CustomPageNumberPagination
|
||||||
from .models import AIPrompt, AuthorProfile, Strategy
|
from .models import AIPrompt, AuthorProfile, Strategy
|
||||||
@@ -199,6 +199,7 @@ class AuthorProfileViewSet(AccountModelViewSet):
|
|||||||
"""
|
"""
|
||||||
queryset = AuthorProfile.objects.all()
|
queryset = AuthorProfile.objects.all()
|
||||||
serializer_class = AuthorProfileSerializer
|
serializer_class = AuthorProfileSerializer
|
||||||
|
permission_classes = [IsAuthenticatedAndActive, IsViewerOrAbove]
|
||||||
throttle_scope = 'system'
|
throttle_scope = 'system'
|
||||||
throttle_classes = [DebugScopedRateThrottle]
|
throttle_classes = [DebugScopedRateThrottle]
|
||||||
|
|
||||||
@@ -216,6 +217,7 @@ class StrategyViewSet(AccountModelViewSet):
|
|||||||
"""
|
"""
|
||||||
queryset = Strategy.objects.all()
|
queryset = Strategy.objects.all()
|
||||||
serializer_class = StrategySerializer
|
serializer_class = StrategySerializer
|
||||||
|
permission_classes = [IsAuthenticatedAndActive, IsViewerOrAbove]
|
||||||
throttle_scope = 'system'
|
throttle_scope = 'system'
|
||||||
throttle_classes = [DebugScopedRateThrottle]
|
throttle_classes = [DebugScopedRateThrottle]
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ from igny8_core.api.base import SiteSectorModelViewSet
|
|||||||
from igny8_core.api.pagination import CustomPageNumberPagination
|
from igny8_core.api.pagination import CustomPageNumberPagination
|
||||||
from igny8_core.api.response import success_response, error_response
|
from igny8_core.api.response import success_response, error_response
|
||||||
from igny8_core.api.throttles import DebugScopedRateThrottle
|
from igny8_core.api.throttles import DebugScopedRateThrottle
|
||||||
|
from igny8_core.api.permissions import IsAuthenticatedAndActive, IsViewerOrAbove, IsEditorOrAbove
|
||||||
from .models import Tasks, Images, Content
|
from .models import Tasks, Images, Content
|
||||||
from .serializers import TasksSerializer, ImagesSerializer, ContentSerializer
|
from .serializers import TasksSerializer, ImagesSerializer, ContentSerializer
|
||||||
|
|
||||||
@@ -19,6 +20,7 @@ class TasksViewSet(SiteSectorModelViewSet):
|
|||||||
"""
|
"""
|
||||||
queryset = Tasks.objects.select_related('content_record')
|
queryset = Tasks.objects.select_related('content_record')
|
||||||
serializer_class = TasksSerializer
|
serializer_class = TasksSerializer
|
||||||
|
permission_classes = [IsAuthenticatedAndActive, IsViewerOrAbove]
|
||||||
pagination_class = CustomPageNumberPagination # Explicitly use custom pagination
|
pagination_class = CustomPageNumberPagination # Explicitly use custom pagination
|
||||||
throttle_scope = 'writer'
|
throttle_scope = 'writer'
|
||||||
throttle_classes = [DebugScopedRateThrottle]
|
throttle_classes = [DebugScopedRateThrottle]
|
||||||
@@ -379,6 +381,7 @@ class ImagesViewSet(SiteSectorModelViewSet):
|
|||||||
"""
|
"""
|
||||||
queryset = Images.objects.all()
|
queryset = Images.objects.all()
|
||||||
serializer_class = ImagesSerializer
|
serializer_class = ImagesSerializer
|
||||||
|
permission_classes = [IsAuthenticatedAndActive, IsViewerOrAbove]
|
||||||
pagination_class = CustomPageNumberPagination
|
pagination_class = CustomPageNumberPagination
|
||||||
throttle_scope = 'writer'
|
throttle_scope = 'writer'
|
||||||
throttle_classes = [DebugScopedRateThrottle]
|
throttle_classes = [DebugScopedRateThrottle]
|
||||||
@@ -777,6 +780,7 @@ class ContentViewSet(SiteSectorModelViewSet):
|
|||||||
"""
|
"""
|
||||||
queryset = Content.objects.all()
|
queryset = Content.objects.all()
|
||||||
serializer_class = ContentSerializer
|
serializer_class = ContentSerializer
|
||||||
|
permission_classes = [IsAuthenticatedAndActive, IsViewerOrAbove]
|
||||||
pagination_class = CustomPageNumberPagination
|
pagination_class = CustomPageNumberPagination
|
||||||
throttle_scope = 'writer'
|
throttle_scope = 'writer'
|
||||||
throttle_classes = [DebugScopedRateThrottle]
|
throttle_classes = [DebugScopedRateThrottle]
|
||||||
|
|||||||
@@ -134,12 +134,13 @@ export function usePersistentToggle(
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
const endpoint = getEndpoint.replace('{id}', resourceId);
|
const endpoint = getEndpoint.replace('{id}', resourceId);
|
||||||
|
// fetchAPI extracts data from unified format {success: true, data: {...}}
|
||||||
|
// So result IS the data object, not wrapped
|
||||||
const result = await fetchAPI(endpoint);
|
const result = await fetchAPI(endpoint);
|
||||||
|
|
||||||
if (result.success && result.data) {
|
if (result && typeof result === 'object') {
|
||||||
const apiData = result.data;
|
setData(result);
|
||||||
setData(apiData);
|
const newEnabled = extractEnabled(result);
|
||||||
const newEnabled = extractEnabled(apiData);
|
|
||||||
setEnabled(newEnabled);
|
setEnabled(newEnabled);
|
||||||
} else {
|
} else {
|
||||||
// No data yet - use initial state
|
// No data yet - use initial state
|
||||||
|
|||||||
@@ -333,6 +333,9 @@ export default function Integration() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
// fetchAPI extracts data from unified format {success: true, data: {...}}
|
||||||
|
// But test endpoint may return {success: true, ...} directly (not wrapped)
|
||||||
|
// So data could be either the extracted data object or the full response
|
||||||
const data = await fetchAPI(`/v1/system/settings/integrations/${selectedIntegration}/test/`, {
|
const data = await fetchAPI(`/v1/system/settings/integrations/${selectedIntegration}/test/`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
@@ -341,24 +344,51 @@ export default function Integration() {
|
|||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
if (data.success) {
|
// Handle both unified format (extracted) and direct format
|
||||||
toast.success(data.message || 'API connection test successful!');
|
// If data has success field, it's the direct response (not extracted)
|
||||||
if (data.response) {
|
// If data doesn't have success but has other fields, it's extracted data (successful)
|
||||||
toast.info(`Response: ${data.response}`);
|
if (data && typeof data === 'object') {
|
||||||
}
|
if (data.success === true || data.success === false) {
|
||||||
if (data.tokens_used) {
|
// Direct response format (not extracted by fetchAPI)
|
||||||
toast.info(`Tokens used: ${data.tokens_used}`);
|
if (data.success) {
|
||||||
}
|
toast.success(data.message || 'API connection test successful!');
|
||||||
|
if (data.response) {
|
||||||
|
toast.info(`Response: ${data.response}`);
|
||||||
|
}
|
||||||
|
if (data.tokens_used) {
|
||||||
|
toast.info(`Tokens used: ${data.tokens_used}`);
|
||||||
|
}
|
||||||
|
|
||||||
// Update validation status to success
|
// Update validation status to success
|
||||||
if (selectedIntegration) {
|
if (selectedIntegration) {
|
||||||
setValidationStatuses(prev => ({
|
setValidationStatuses(prev => ({
|
||||||
...prev,
|
...prev,
|
||||||
[selectedIntegration]: 'success',
|
[selectedIntegration]: 'success',
|
||||||
}));
|
}));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new Error(data.error || data.message || 'Connection test failed');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Extracted data format (successful response)
|
||||||
|
toast.success('API connection test successful!');
|
||||||
|
if (data.response) {
|
||||||
|
toast.info(`Response: ${data.response}`);
|
||||||
|
}
|
||||||
|
if (data.tokens_used) {
|
||||||
|
toast.info(`Tokens used: ${data.tokens_used}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update validation status to success
|
||||||
|
if (selectedIntegration) {
|
||||||
|
setValidationStatuses(prev => ({
|
||||||
|
...prev,
|
||||||
|
[selectedIntegration]: 'success',
|
||||||
|
}));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
throw new Error(data.error || 'Connection test failed');
|
throw new Error('Invalid response format');
|
||||||
}
|
}
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
console.error('Error testing connection:', error);
|
console.error('Error testing connection:', error);
|
||||||
|
|||||||
@@ -640,34 +640,24 @@ export async function autoClusterKeywords(keywordIds: number[], sectorId?: numbe
|
|||||||
const requestBody = { ids: keywordIds, sector_id: sectorId };
|
const requestBody = { ids: keywordIds, sector_id: sectorId };
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// fetchAPI will automatically extract data from unified format
|
// fetchAPI extracts data from unified format {success: true, data: {...}}
|
||||||
// For action endpoints, response is {success: true, data: {...}}
|
// So response is already the data object: {task_id: "...", ...}
|
||||||
// fetchAPI extracts and returns the data field, so response should already be the data object
|
|
||||||
const response = await fetchAPI(endpoint, {
|
const response = await fetchAPI(endpoint, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: JSON.stringify(requestBody),
|
body: JSON.stringify(requestBody),
|
||||||
});
|
});
|
||||||
|
|
||||||
// After fetchAPI processing, response should be the data object (not wrapped in success/data)
|
// Wrap extracted data with success: true for frontend compatibility
|
||||||
// But check if it's still wrapped (shouldn't happen, but for safety)
|
|
||||||
if (response && typeof response === 'object') {
|
if (response && typeof response === 'object') {
|
||||||
if ('success' in response && response.success === false) {
|
return { success: true, ...response } as any;
|
||||||
// Error response - return as-is
|
|
||||||
return response as any;
|
|
||||||
}
|
|
||||||
// If response has data field, extract it
|
|
||||||
if ('data' in response && response.data) {
|
|
||||||
return { success: true, ...response.data } as any;
|
|
||||||
}
|
|
||||||
// Response is already the data object (after fetchAPI extraction)
|
|
||||||
// Ensure it has success: true
|
|
||||||
if (!('success' in response)) {
|
|
||||||
return { success: true, ...response } as any;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return response as any;
|
return { success: true, ...response } as any;
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
|
// Error responses are thrown by fetchAPI, but wrap them for consistency
|
||||||
|
if (error.response && typeof error.response === 'object') {
|
||||||
|
return { success: false, error: error.message, ...error.response } as any;
|
||||||
|
}
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -677,13 +667,24 @@ export async function autoGenerateIdeas(clusterIds: number[]): Promise<{ success
|
|||||||
const requestBody = { ids: clusterIds };
|
const requestBody = { ids: clusterIds };
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
// fetchAPI extracts data from unified format {success: true, data: {...}}
|
||||||
|
// So response is already the data object: {task_id: "...", ...}
|
||||||
const response = await fetchAPI(endpoint, {
|
const response = await fetchAPI(endpoint, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: JSON.stringify(requestBody),
|
body: JSON.stringify(requestBody),
|
||||||
});
|
});
|
||||||
|
|
||||||
return response;
|
// Wrap extracted data with success: true for frontend compatibility
|
||||||
|
if (response && typeof response === 'object') {
|
||||||
|
return { success: true, ...response } as any;
|
||||||
|
}
|
||||||
|
|
||||||
|
return { success: true, ...response } as any;
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
|
// Error responses are thrown by fetchAPI, but wrap them for consistency
|
||||||
|
if (error.response && typeof error.response === 'object') {
|
||||||
|
return { success: false, error: error.message, ...error.response } as any;
|
||||||
|
}
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -693,13 +694,24 @@ export async function generateSingleIdea(ideaId: string | number, clusterId: num
|
|||||||
const requestBody = { cluster_id: clusterId };
|
const requestBody = { cluster_id: clusterId };
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
// fetchAPI extracts data from unified format {success: true, data: {...}}
|
||||||
|
// So response is already the data object: {task_id: "...", ...}
|
||||||
const response = await fetchAPI(endpoint, {
|
const response = await fetchAPI(endpoint, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: JSON.stringify(requestBody),
|
body: JSON.stringify(requestBody),
|
||||||
});
|
});
|
||||||
|
|
||||||
return response;
|
// Wrap extracted data with success: true for frontend compatibility
|
||||||
|
if (response && typeof response === 'object') {
|
||||||
|
return { success: true, ...response } as any;
|
||||||
|
}
|
||||||
|
|
||||||
|
return { success: true, ...response } as any;
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
|
// Error responses are thrown by fetchAPI, but wrap them for consistency
|
||||||
|
if (error.response && typeof error.response === 'object') {
|
||||||
|
return { success: false, error: error.message, ...error.response } as any;
|
||||||
|
}
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1000,13 +1012,24 @@ export async function autoGenerateContent(ids: number[]): Promise<{ success: boo
|
|||||||
const requestBody = { ids };
|
const requestBody = { ids };
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
// fetchAPI extracts data from unified format {success: true, data: {...}}
|
||||||
|
// So response is already the data object: {task_id: "...", ...}
|
||||||
const response = await fetchAPI(endpoint, {
|
const response = await fetchAPI(endpoint, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: JSON.stringify(requestBody),
|
body: JSON.stringify(requestBody),
|
||||||
});
|
});
|
||||||
|
|
||||||
return response;
|
// Wrap extracted data with success: true for frontend compatibility
|
||||||
|
if (response && typeof response === 'object') {
|
||||||
|
return { success: true, ...response } as any;
|
||||||
|
}
|
||||||
|
|
||||||
|
return { success: true, ...response } as any;
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
|
// Error responses are thrown by fetchAPI, but wrap them for consistency
|
||||||
|
if (error.response && typeof error.response === 'object') {
|
||||||
|
return { success: false, error: error.message, ...error.response } as any;
|
||||||
|
}
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1016,13 +1039,24 @@ export async function autoGenerateImages(taskIds: number[]): Promise<{ success:
|
|||||||
const requestBody = { task_ids: taskIds };
|
const requestBody = { task_ids: taskIds };
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
// fetchAPI extracts data from unified format {success: true, data: {...}}
|
||||||
|
// So response is already the data object: {task_id: "...", ...}
|
||||||
const response = await fetchAPI(endpoint, {
|
const response = await fetchAPI(endpoint, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: JSON.stringify(requestBody),
|
body: JSON.stringify(requestBody),
|
||||||
});
|
});
|
||||||
|
|
||||||
return response;
|
// Wrap extracted data with success: true for frontend compatibility
|
||||||
|
if (response && typeof response === 'object') {
|
||||||
|
return { success: true, ...response } as any;
|
||||||
|
}
|
||||||
|
|
||||||
|
return { success: true, ...response } as any;
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
|
// Error responses are thrown by fetchAPI, but wrap them for consistency
|
||||||
|
if (error.response && typeof error.response === 'object') {
|
||||||
|
return { success: false, error: error.message, ...error.response } as any;
|
||||||
|
}
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user