5c17c798c4
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.
226 lines
6.3 KiB
Vue
226 lines
6.3 KiB
Vue
<template>
|
|
<div>
|
|
<v-row>
|
|
<v-col cols="12">
|
|
<v-btn
|
|
prepend-icon="mdi-arrow-left"
|
|
variant="text"
|
|
@click="navigateTo('/schemas')"
|
|
>
|
|
Back to Schemas
|
|
</v-btn>
|
|
</v-col>
|
|
</v-row>
|
|
|
|
<v-row v-if="schema">
|
|
<v-col cols="12">
|
|
<h1 class="text-h3 mb-2">{{ schema.service }}</h1>
|
|
<v-chip class="mr-2">{{ schema.ref }}</v-chip>
|
|
<v-chip color="success">Active</v-chip>
|
|
</v-col>
|
|
</v-row>
|
|
|
|
<v-row v-if="schema">
|
|
<v-col cols="12" md="6">
|
|
<v-card>
|
|
<v-card-title>Details</v-card-title>
|
|
<v-card-text>
|
|
<v-list>
|
|
<v-list-item>
|
|
<v-list-item-title>Service</v-list-item-title>
|
|
<v-list-item-subtitle>{{ schema.service }}</v-list-item-subtitle>
|
|
</v-list-item>
|
|
<v-list-item>
|
|
<v-list-item-title>Ref</v-list-item-title>
|
|
<v-list-item-subtitle>{{ schema.ref }}</v-list-item-subtitle>
|
|
</v-list-item>
|
|
<v-list-item>
|
|
<v-list-item-title>URL</v-list-item-title>
|
|
<v-list-item-subtitle>{{ schema.url }}</v-list-item-subtitle>
|
|
</v-list-item>
|
|
<v-list-item v-if="schema.wsUrl">
|
|
<v-list-item-title>WebSocket URL</v-list-item-title>
|
|
<v-list-item-subtitle>{{ schema.wsUrl }}</v-list-item-subtitle>
|
|
</v-list-item>
|
|
<v-list-item>
|
|
<v-list-item-title>Last Updated</v-list-item-title>
|
|
<v-list-item-subtitle>{{ schema.updatedAt }}</v-list-item-subtitle>
|
|
</v-list-item>
|
|
<v-list-item>
|
|
<v-list-item-title>Updated By</v-list-item-title>
|
|
<v-list-item-subtitle>{{ schema.updatedBy }}</v-list-item-subtitle>
|
|
</v-list-item>
|
|
</v-list>
|
|
</v-card-text>
|
|
</v-card>
|
|
</v-col>
|
|
|
|
<v-col cols="12" md="6">
|
|
<v-card>
|
|
<v-card-title>Actions</v-card-title>
|
|
<v-card-text>
|
|
<v-btn
|
|
block
|
|
prepend-icon="mdi-download"
|
|
variant="outlined"
|
|
class="mb-2"
|
|
@click="downloadSchema"
|
|
>
|
|
Download SDL
|
|
</v-btn>
|
|
<v-btn
|
|
block
|
|
prepend-icon="mdi-content-copy"
|
|
variant="outlined"
|
|
class="mb-2"
|
|
@click="copyToClipboard"
|
|
>
|
|
Copy SDL
|
|
</v-btn>
|
|
<v-btn
|
|
block
|
|
prepend-icon="mdi-graph"
|
|
variant="outlined"
|
|
color="primary"
|
|
@click="viewFederationGraph"
|
|
>
|
|
View Federation Graph
|
|
</v-btn>
|
|
</v-card-text>
|
|
</v-card>
|
|
</v-col>
|
|
</v-row>
|
|
|
|
<v-row v-if="schema">
|
|
<v-col cols="12">
|
|
<v-card>
|
|
<v-card-title class="d-flex justify-space-between align-center">
|
|
<span>Schema Definition (SDL)</span>
|
|
<v-btn
|
|
icon="mdi-content-copy"
|
|
variant="text"
|
|
size="small"
|
|
@click="copyToClipboard"
|
|
/>
|
|
</v-card-title>
|
|
<v-card-text>
|
|
<pre class="sdl-viewer"><code>{{ schema.sdl }}</code></pre>
|
|
</v-card-text>
|
|
</v-card>
|
|
</v-col>
|
|
</v-row>
|
|
|
|
<v-row v-if="!schema && !loading">
|
|
<v-col cols="12" class="text-center py-12">
|
|
<v-icon icon="mdi-alert-circle" size="64" class="mb-4 text-warning" />
|
|
<p class="text-h6">Schema not found</p>
|
|
</v-col>
|
|
</v-row>
|
|
|
|
<v-snackbar v-model="snackbar" :timeout="2000">
|
|
{{ snackbarText }}
|
|
</v-snackbar>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { useAuth0 } from '@auth0/auth0-vue'
|
|
|
|
import { useLatestSchemaQuery } from '~/graphql/generated'
|
|
|
|
const auth0 = useAuth0()
|
|
const route = useRoute()
|
|
const _config = useRuntimeConfig()
|
|
|
|
// Parse the ID which should contain both ref and service info
|
|
// The ID format from backend is typically: orgId_ref_service or similar
|
|
const schemaId = route.params.id as string
|
|
|
|
const snackbar = ref(false)
|
|
const snackbarText = ref('')
|
|
|
|
// We need to fetch all schemas and find the matching one
|
|
// Since we don't have a direct query for a single subgraph by ID,
|
|
// we'll need to get it from the URL or store it in a better format
|
|
// For now, let's extract ref from the route query or use a default
|
|
const schemaRef = computed(() => {
|
|
return (route.query.ref as string) || 'production'
|
|
})
|
|
|
|
// Fetch latest schema for the ref
|
|
const latestSchemaQuery = useLatestSchemaQuery(() => ({
|
|
ref: schemaRef.value,
|
|
}), () => ({
|
|
skip: !auth0.isAuthenticated.value,
|
|
}))
|
|
|
|
// Find the specific subgraph matching our ID
|
|
const schema = computed(() => {
|
|
if (!latestSchemaQuery.result.value?.latestSchema?.subGraphs) return null
|
|
|
|
const subgraph = latestSchemaQuery.result.value.latestSchema.subGraphs.find(
|
|
s => s.id === schemaId,
|
|
)
|
|
|
|
if (!subgraph) return null
|
|
|
|
return {
|
|
id: subgraph.id,
|
|
service: subgraph.service,
|
|
ref: schemaRef.value,
|
|
url: subgraph.url || 'N/A',
|
|
wsUrl: subgraph.wsUrl,
|
|
updatedAt: new Date(subgraph.changedAt).toLocaleString(),
|
|
updatedBy: subgraph.changedBy,
|
|
sdl: subgraph.sdl,
|
|
}
|
|
})
|
|
|
|
const loading = computed(() => latestSchemaQuery.loading.value)
|
|
|
|
const downloadSchema = () => {
|
|
if (!schema.value) return
|
|
|
|
const blob = new Blob([schema.value.sdl], { type: 'text/plain' })
|
|
const url = URL.createObjectURL(blob)
|
|
const a = document.createElement('a')
|
|
a.href = url
|
|
a.download = `${schema.value.service}-${schema.value.ref}.graphql`
|
|
a.click()
|
|
URL.revokeObjectURL(url)
|
|
|
|
snackbarText.value = 'Schema downloaded'
|
|
snackbar.value = true
|
|
}
|
|
|
|
const copyToClipboard = async () => {
|
|
if (!schema.value) return
|
|
|
|
try {
|
|
await navigator.clipboard.writeText(schema.value.sdl)
|
|
snackbarText.value = 'SDL copied to clipboard'
|
|
snackbar.value = true
|
|
} catch (_err) {
|
|
snackbarText.value = 'Failed to copy'
|
|
snackbar.value = true
|
|
}
|
|
}
|
|
|
|
const viewFederationGraph = () => {
|
|
if (!schema.value?.ref) return
|
|
navigateTo(`/graph/${schema.value.ref}`)
|
|
}
|
|
</script>
|
|
|
|
<style scoped>
|
|
.sdl-viewer {
|
|
background: #f5f5f5;
|
|
padding: 16px;
|
|
border-radius: 4px;
|
|
overflow-x: auto;
|
|
font-family: Monaco, Menlo, 'Ubuntu Mono', monospace;
|
|
font-size: 14px;
|
|
line-height: 1.5;
|
|
}
|
|
</style>
|