-
+
import { onMounted, ref, watch } from 'vue'
-import { useRoute } from 'vue-router'
+import { useRoute, useRouter } from 'vue-router'
import {
ArrowLeftIcon,
CheckIcon,
@@ -10,8 +10,10 @@ import {
import { getProject } from '../api/client'
import MarkdownContent from '../components/markdown/MarkdownContent.vue'
import type { Project } from '../types/project'
+import { projectPath } from '../utils/projectRoutes'
const route = useRoute()
+const router = useRouter()
const project = ref(null)
const loading = ref(true)
@@ -22,7 +24,13 @@ async function loadProject() {
error.value = ''
try {
- project.value = await getProject(String(route.params.id))
+ const loadedProject = await getProject(String(route.params.id))
+ project.value = loadedProject
+
+ const canonicalPath = projectPath(loadedProject)
+ if (route.path !== canonicalPath) {
+ await router.replace(canonicalPath)
+ }
} catch (err) {
error.value =
err instanceof Error
@@ -38,9 +46,7 @@ onMounted(loadProject)
-
+
@@ -73,10 +79,10 @@ onMounted(loadProject)
-
-
+
+
{{ project.name.charAt(0).toUpperCase() }}
@@ -85,7 +91,7 @@ onMounted(loadProject)
{{ project.name }}
@@ -102,7 +108,7 @@ onMounted(loadProject)
{{ project.short_description }}
@@ -127,9 +133,11 @@ onMounted(loadProject)
+
@@ -749,7 +619,7 @@ onMounted(async () => {
the directory.
-
+
@@ -757,11 +627,11 @@ onMounted(async () => {
- Listing status
+ Project status
Ready
diff --git a/frontend/src/router/index.ts b/frontend/src/router/index.ts
index 42118b6..177ff79 100644
--- a/frontend/src/router/index.ts
+++ b/frontend/src/router/index.ts
@@ -10,8 +10,26 @@ export const router = createRouter({
routes: [
{ path: '/', component: HomePage },
{
- path: '/bots/:id',
- component: () => import('../pages/BotDetailPage.vue'),
+ path: '/browse',
+ component: () => import('../pages/BrowsePage.vue'),
+ },
+ {
+ path: '/projects/:id',
+ alias: [
+ '/bots/:id',
+ '/bridges/:id',
+ '/clients/:id',
+ '/frameworks/:id',
+ '/integrations/:id',
+ '/sdks/:id',
+ '/servers/:id',
+ ],
+ component: () => import('../pages/ProjectDetailPage.vue'),
+ },
+ {
+ path: '/projects/:id/edit',
+ component: () => import('../pages/SubmitPage.vue'),
+ meta: { requiresAuth: true },
},
{ path: '/login', component: LoginPage },
{
diff --git a/frontend/src/types/project.ts b/frontend/src/types/project.ts
index 5af2b92..a3ff7f3 100644
--- a/frontend/src/types/project.ts
+++ b/frontend/src/types/project.ts
@@ -29,6 +29,7 @@ export type ProjectListItem = {
labels: Label[]
owner: ProjectOwner
created_at: string
+ updated_at: string
}
export type Project = ProjectListItem
diff --git a/frontend/src/utils/projectRoutes.ts b/frontend/src/utils/projectRoutes.ts
new file mode 100644
index 0000000..2a1383b
--- /dev/null
+++ b/frontend/src/utils/projectRoutes.ts
@@ -0,0 +1,18 @@
+import type { ProjectListItem } from '../types/project'
+
+const projectTypePaths: Record = {
+ Bot: 'bots',
+ Bridges: 'bridges',
+ Clients: 'clients',
+ Framework: 'frameworks',
+ Integrations: 'integrations',
+ SDK: 'sdks',
+ Server: 'servers',
+}
+
+export function projectPath(
+ project: Pick,
+) {
+ const segment = projectTypePaths[project.project_type.name] ?? 'projects'
+ return `/${segment}/${project.id}`
+}
import { onMounted, ref, watch } from 'vue'
-import { useRoute } from 'vue-router'
+import { useRoute, useRouter } from 'vue-router'
import {
ArrowLeftIcon,
CheckIcon,
@@ -10,8 +10,10 @@ import {
import { getProject } from '../api/client'
import MarkdownContent from '../components/markdown/MarkdownContent.vue'
import type { Project } from '../types/project'
+import { projectPath } from '../utils/projectRoutes'
const route = useRoute()
+const router = useRouter()
const project = ref
{{ project.short_description }}
- Listing status
+ Project status
{{ project.name }}
@@ -102,7 +108,7 @@ onMounted(loadProject)