Files
schemas-app/app/pages/schemas/index.vue
T
argoyle 5c17c798c4 feat: enhance authentication error handling and schema fetching
Handle authentication errors related to consent and login in the Apollo 
client by redirecting users to the Auth0 login page as necessary. Update
the schema-fetching logic to support dynamic references from the URL, 
removing mock data and improving overall data integrity in the 
application.
Ensure proper loading states during the fetching process.
2025-11-23 14:01:32 +01:00

164 lines
4.7 KiB
Vue

<template>
<div>
<v-row>
<v-col cols="12">
<h1 class="text-h3 mb-4">Published Schemas</h1>
</v-col>
</v-row>
<v-row v-if="!auth0.isAuthenticated.value">
<v-col cols="12">
<v-alert type="info" variant="tonal">
Please log in to view published schemas.
</v-alert>
</v-col>
</v-row>
<v-row v-else>
<v-col cols="12" md="3">
<v-select
v-model="selectedRef"
:items="refs"
label="Select Ref"
prepend-icon="mdi-source-branch"
variant="outlined"
:disabled="!selectedOrganization"
/>
</v-col>
<v-col cols="12" md="9">
<v-text-field
v-model="search"
label="Search schemas"
prepend-icon="mdi-magnify"
variant="outlined"
clearable
/>
</v-col>
</v-row>
<v-row v-if="auth0.isAuthenticated.value && latestSchema.loading.value">
<v-col cols="12" class="text-center">
<v-progress-circular indeterminate size="64" />
<p class="mt-4">Loading schemas for {{ selectedRef }}...</p>
</v-col>
</v-row>
<v-row v-else-if="auth0.isAuthenticated.value && latestSchema.error.value">
<v-col cols="12">
<v-alert type="error" variant="tonal">
Error loading schemas: {{ latestSchema.error.value.message }}
</v-alert>
</v-col>
</v-row>
<v-row v-else-if="auth0.isAuthenticated.value">
<v-col
v-for="schema in filteredSchemas"
:key="schema.id"
cols="12"
md="6"
lg="4"
>
<v-card hover @click="navigateTo(`/schemas/${schema.id}?ref=${schema.ref}`)">
<v-card-title>
<v-icon icon="mdi-graphql" class="mr-2" />
{{ schema.service }}
</v-card-title>
<v-card-subtitle>{{ schema.ref }}</v-card-subtitle>
<v-card-text>
<div class="mb-2">
<strong>URL:</strong> {{ schema.url }}
</div>
<div class="text-caption text-grey">
Updated: {{ schema.updatedAt }}
</div>
</v-card-text>
<v-card-actions>
<v-btn variant="text" color="primary">
View Schema
</v-btn>
<v-spacer />
<v-chip size="small" color="success">Active</v-chip>
</v-card-actions>
</v-card>
</v-col>
<v-col v-if="filteredSchemas.length === 0" cols="12" class="text-center py-12">
<v-icon icon="mdi-graphql" size="64" class="mb-4 text-grey" />
<p class="text-h6 text-grey">No schemas found</p>
<p class="text-grey">{{ search ? 'Try a different search term' : 'Publish your first schema to get started' }}</p>
</v-col>
</v-row>
</div>
</template>
<script setup lang="ts">
import { useAuth0 } from '@auth0/auth0-vue'
import { watch } from 'vue'
import { useOrganizationSelector } from '~/composables/useOrganizationSelector'
import {
useLatestSchemaQuery,
} from '~/graphql/generated'
const auth0 = useAuth0()
const { selectedOrganization } = useOrganizationSelector()
const selectedRef = ref('production')
const search = ref('')
// Get available refs from the selected organization
const refs = computed(() => {
if (!selectedOrganization.value) return ['production', 'staging', 'development']
const allRefs = new Set<string>()
selectedOrganization.value.apiKeys?.forEach(key => {
key.refs?.forEach(ref => allRefs.add(ref))
})
return Array.from(allRefs).length > 0 ? Array.from(allRefs) : ['production', 'staging', 'development']
})
// Fetch schema for selected ref
const latestSchema = useLatestSchemaQuery(() => ({
ref: selectedRef.value,
}), () => ({
skip: !auth0.isAuthenticated.value || !selectedRef.value,
}))
const schemas = computed(() => {
if (!latestSchema.result.value?.latestSchema?.subGraphs) return []
return latestSchema.result.value.latestSchema.subGraphs.map(subgraph => ({
id: subgraph.id,
service: subgraph.service,
ref: selectedRef.value,
url: subgraph.url || 'N/A',
wsUrl: subgraph.wsUrl,
updatedAt: new Date(subgraph.changedAt).toLocaleString(),
changedBy: subgraph.changedBy,
}))
})
const filteredSchemas = computed(() => {
let filtered = schemas.value
if (search.value) {
const searchLower = search.value.toLowerCase()
filtered = filtered.filter(s =>
s.service.toLowerCase().includes(searchLower) ||
s.url.toLowerCase().includes(searchLower),
)
}
return filtered
})
// Watch for ref changes and ensure the first ref is selected
watch(refs, (newRefs) => {
if (newRefs.length > 0 && !newRefs.includes(selectedRef.value)) {
selectedRef.value = newRefs[0]
}
}, { immediate: true })
</script>