corrad-af-2024/components/api-platform/CollectionsSidebar.vue

318 lines
10 KiB
Vue

<template>
<div class="w-80 bg-white dark:bg-gray-800 border-r border-gray-200 dark:border-gray-700 flex flex-col">
<!-- Header -->
<div class="p-4 border-b border-gray-200 dark:border-gray-700">
<div class="flex items-center justify-between">
<h2 class="text-lg font-semibold text-gray-900 dark:text-white">Collections</h2>
<div class="flex items-center gap-2">
<rs-button
variant="secondary-outline"
size="sm"
@click="showCreateCollectionModal = true"
class="p-2"
>
<Icon name="ic:outline-add" size="16" />
</rs-button>
<rs-button
variant="text"
size="sm"
@click="$emit('close')"
class="p-2 lg:hidden"
>
<Icon name="ic:outline-close" size="16" />
</rs-button>
</div>
</div>
</div>
<!-- Recent Requests -->
<div v-if="requestHistory.length > 0" class="border-b border-gray-200 dark:border-gray-700 p-4">
<div class="flex items-center justify-between mb-2">
<h3 class="text-sm font-medium text-gray-900 dark:text-white">Recent</h3>
<span class="text-xs text-gray-500 dark:text-gray-400">Last 5 requests</span>
</div>
<p class="text-xs text-gray-500 dark:text-gray-400 mb-3">Your most recently sent requests for quick access</p>
<div class="space-y-1">
<div
v-for="request in requestHistory.slice(0, 5)"
:key="request.id"
@click="loadHistoryRequest(request)"
class="flex items-center gap-2 p-2 rounded-lg hover:bg-gray-50 dark:hover:bg-gray-700 cursor-pointer"
>
<rs-badge :variant="getMethodVariant(request.method)" size="sm" class="w-12 text-xs">
{{ request.method }}
</rs-badge>
<div class="flex-1 min-w-0">
<p class="text-sm text-gray-700 dark:text-gray-300 truncate">{{ request.name }}</p>
<p class="text-xs text-gray-500 dark:text-gray-400">{{ formatDate(request.timestamp) }}</p>
</div>
</div>
</div>
</div>
<!-- Collections List -->
<div class="flex-1 overflow-y-auto p-2">
<div v-if="collections.length === 0" class="text-center py-8 text-gray-500 dark:text-gray-400">
<Icon name="ic:outline-folder-open" size="48" class="mx-auto mb-4 opacity-50" />
<p class="text-sm mb-4">No collections yet</p>
<div class="flex justify-center">
<rs-button
variant="primary"
size="sm"
@click="showCreateCollectionModal = true"
class="flex items-center gap-2"
>
<Icon name="ic:outline-add" size="14" />
Create Collection
</rs-button>
</div>
</div>
<div v-else class="space-y-1">
<div
v-for="collection in collections"
:key="collection.id"
class="group"
>
<!-- Collection Header -->
<div
@click="toggleCollection(collection.id)"
class="flex items-center gap-2 p-3 rounded-lg hover:bg-gray-50 dark:hover:bg-gray-700 cursor-pointer group/header"
>
<Icon
:name="expandedCollections.has(collection.id) ? 'ic:outline-expand-more' : 'ic:outline-chevron-right'"
size="16"
class="text-gray-400 transition-transform"
/>
<Icon name="ic:outline-folder" size="16" class="text-blue-500" />
<span class="flex-1 text-sm font-medium text-gray-900 dark:text-white truncate">
{{ collection.name }}
</span>
<div class="opacity-0 group-hover/header:opacity-100 flex items-center gap-1">
<rs-button
variant="text"
size="sm"
@click.stop="editCollection(collection)"
class="p-1"
>
<Icon name="ic:outline-edit" size="14" />
</rs-button>
<rs-button
variant="text"
size="sm"
@click.stop="deleteCollection(collection.id)"
class="p-1 text-red-500 hover:text-red-600"
>
<Icon name="ic:outline-delete" size="14" />
</rs-button>
</div>
</div>
<!-- Collection Requests -->
<div v-if="expandedCollections.has(collection.id)" class="ml-6 space-y-1">
<div
v-for="request in collection.requests"
:key="request.id"
@click="loadRequest(request)"
class="flex items-center gap-2 p-2 rounded-lg hover:bg-gray-50 dark:hover:bg-gray-700 cursor-pointer group/request"
>
<rs-badge :variant="getMethodVariant(request.method)" size="sm" class="w-12 text-xs">
{{ request.method }}
</rs-badge>
<span class="flex-1 text-sm text-gray-700 dark:text-gray-300 truncate">
{{ request.name }}
</span>
<div class="opacity-0 group-hover/request:opacity-100 flex items-center gap-1">
<rs-button
variant="text"
size="sm"
@click.stop="editRequest(request)"
class="p-1"
>
<Icon name="ic:outline-edit" size="12" />
</rs-button>
<rs-button
variant="text"
size="sm"
@click.stop="deleteRequest(collection.id, request.id)"
class="p-1 text-red-500 hover:text-red-600"
>
<Icon name="ic:outline-delete" size="12" />
</rs-button>
</div>
</div>
<!-- Add Request Button -->
<rs-button
variant="text"
size="sm"
@click="addRequestToCollection(collection.id)"
class="w-full justify-start text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200"
>
<Icon name="ic:outline-add" size="14" class="mr-2" />
Add Request
</rs-button>
</div>
</div>
</div>
</div>
<!-- Create Collection Modal -->
<CreateCollectionModal
v-if="showCreateCollectionModal"
@close="showCreateCollectionModal = false"
@created="onCollectionCreated"
/>
</div>
</template>
<script setup>
import CreateCollectionModal from './CreateCollectionModal.vue'
const emit = defineEmits(['close'])
const { getMethodVariant } = useApiRequest()
const {
collections,
requestHistory,
httpMethod,
requestUrl,
requestParams,
requestHeaders,
requestAuth,
requestBody,
requestName,
showNotification
} = useApiPlatform()
const showCreateCollectionModal = ref(false)
const expandedCollections = ref(new Set())
// Initialize with all collections expanded
watch(collections, (newCollections) => {
newCollections.forEach(collection => {
expandedCollections.value.add(collection.id)
})
}, { immediate: true })
const toggleCollection = (collectionId) => {
if (expandedCollections.value.has(collectionId)) {
expandedCollections.value.delete(collectionId)
} else {
expandedCollections.value.add(collectionId)
}
}
const loadRequest = (request) => {
httpMethod.value = request.method
requestUrl.value = request.url
requestName.value = request.name
// Load request data if available
if (request.params) requestParams.value = request.params
if (request.headers) requestHeaders.value = request.headers
if (request.auth) requestAuth.value = request.auth
if (request.body) requestBody.value = request.body
showNotification(`Loaded request: ${request.name}`, 'success')
}
const loadHistoryRequest = (request) => {
httpMethod.value = request.method
requestUrl.value = request.url
requestName.value = request.name
showNotification(`Loaded from history: ${request.name}`, 'success')
}
const addRequestToCollection = (collectionId) => {
const collection = collections.value.find(c => c.id === collectionId)
if (!collection) return
const newRequest = {
id: Date.now(),
name: 'New Request',
method: 'GET',
url: '',
params: [],
headers: [],
auth: { type: 'none' },
body: { type: 'raw', raw: '' }
}
collection.requests.push(newRequest)
saveCollections()
showNotification('Request added to collection', 'success')
}
const editCollection = (collection) => {
const newName = prompt('Collection name:', collection.name)
if (newName && newName.trim()) {
collection.name = newName.trim()
saveCollections()
showNotification('Collection updated', 'success')
}
}
const deleteCollection = (collectionId) => {
if (confirm('Are you sure you want to delete this collection?')) {
const index = collections.value.findIndex(c => c.id === collectionId)
if (index !== -1) {
collections.value.splice(index, 1)
saveCollections()
showNotification('Collection deleted', 'success')
}
}
}
const editRequest = (request) => {
const newName = prompt('Request name:', request.name)
if (newName && newName.trim()) {
request.name = newName.trim()
saveCollections()
showNotification('Request updated', 'success')
}
}
const deleteRequest = (collectionId, requestId) => {
if (confirm('Are you sure you want to delete this request?')) {
const collection = collections.value.find(c => c.id === collectionId)
if (collection) {
const index = collection.requests.findIndex(r => r.id === requestId)
if (index !== -1) {
collection.requests.splice(index, 1)
saveCollections()
showNotification('Request deleted', 'success')
}
}
}
}
const onCollectionCreated = (collection) => {
collections.value.push(collection)
expandedCollections.value.add(collection.id)
saveCollections()
showNotification('Collection created', 'success')
}
const saveCollections = () => {
localStorage.setItem('api-platform-collections', JSON.stringify(collections.value))
}
const formatDate = (timestamp) => {
return new Date(timestamp).toLocaleString()
}
// Load collections from localStorage on mount
onMounted(() => {
const saved = localStorage.getItem('api-platform-collections')
if (saved) {
try {
const parsed = JSON.parse(saved)
collections.value.splice(0, collections.value.length, ...parsed)
} catch (e) {
console.error('Failed to load collections:', e)
}
}
})
</script>