4daebf8c-dc42-4579-b104-0ed8afe17301 — Commit e2d69b74
Changed files
src/api/client.ts | 14 ++++++++-- src/components/AppCard.vue | 4 +-- src/components/DeeplinkCard.vue | 2 -- src/components/OrgSidebar.vue | 18 ++++++------- src/router/index.ts | 12 ++++----- src/stores/organizations.ts | 13 ++++----- src/types/index.ts | 1 + src/views/AddAppView.vue | 59 +++++++++++++++++++++++++---------------- src/views/AddDeeplinkView.vue | 34 ++++++++++++++++-------- src/views/AddOrgView.vue | 5 ++-- src/views/AppDetailView.vue | 45 ++++++++++++++++++------------- src/views/HomeView.vue | 44 ++++++++++++++++-------------- src/views/LaunchHistoryView.vue | 9 ++++++- 13 files changed, 157 insertions(+), 103 deletions(-)
Diff
diff --git a/src/api/client.ts b/src/api/client.ts
index bb166c7..e96ead7 100644
--- a/src/api/client.ts
+++ b/src/api/client.ts
@@ -41,12 +41,17 @@ export async function getOrganizations() {
return response.data
}
-export const createOrganization = (name: string) =>
- api.post<Organization>('/organizations', {name}).then(r => r.data)
+export async function createOrganization(name: string) {
+ const response = await api.post<Organization>('/organizations', {"name": name})
+ return response.data
+}
export const getOrganization = (orgId: string) =>
api.get<Organization>(`/organizations/${orgId}`).then(r => r.data)
+export const getOrganizationBySlug = (slug: string) =>
+ api.get<Organization>(`/organizations/by-slug/${slug}`).then(r => r.data)
+
export const deleteOrganization = (orgId: string) =>
api.delete(`/organizations/${orgId}`)
@@ -65,6 +70,11 @@ export async function createApp(
export const getApp = (orgId: string, appId: string) =>
api.get<ApiApp>(`/organizations/${orgId}/apps/${appId}`).then(r => normalizeApp(r.data))
+export const getAppBySlug = (orgSlug: string, appSlug: string) =>
+ api
+ .get<ApiApp>(`/organizations/by-slug/${orgSlug}/apps/by-slug/${appSlug}`)
+ .then(r => normalizeApp(r.data))
+
export async function updateApp(
orgId: string,
appId: string,
diff --git a/src/components/AppCard.vue b/src/components/AppCard.vue
index eff1000..ca89e3f 100644
--- a/src/components/AppCard.vue
+++ b/src/components/AppCard.vue
@@ -4,13 +4,13 @@ import type { App } from '@/types'
const props = defineProps<{
app: App
- orgId: string
+ orgSlug: string
}>()
const router = useRouter()
function open() {
- router.push(`/org/${props.orgId}/app/${props.app.id}`)
+ router.push(`/org/${props.orgSlug}/app/${props.app.slug}`)
}
</script>
diff --git a/src/components/DeeplinkCard.vue b/src/components/DeeplinkCard.vue
index d279fab..2b4bf6c 100644
--- a/src/components/DeeplinkCard.vue
+++ b/src/components/DeeplinkCard.vue
@@ -3,8 +3,6 @@ import type {DeeplinkTemplate, Environment} from '@/types'
const props = defineProps<{
deeplink: DeeplinkTemplate
- orgId: string
- appId: string
environment: Environment | null
}>()
diff --git a/src/components/OrgSidebar.vue b/src/components/OrgSidebar.vue
index 8fa022a..b46bcb9 100644
--- a/src/components/OrgSidebar.vue
+++ b/src/components/OrgSidebar.vue
@@ -11,10 +11,10 @@ const orgStore = useOrganizationsStore()
const orgsError = ref<string | null>(null)
-const currentOrgId = computed(() => route.params.orgId as string | undefined)
+const currentOrgSlug = computed(() => route.params.orgSlug as string | undefined)
-function selectOrg(orgId: string) {
- router.push(`/org/${orgId}`)
+function selectOrg(slug: string) {
+ router.push(`/org/${slug}`)
emit('navigate')
}
@@ -33,11 +33,11 @@ async function fetchOrgs() {
}
}
-function removeOrg(e: Event, orgId: string) {
+function removeOrg(e: Event, org: { id: string; slug: string }) {
e.stopPropagation()
if (confirm('Remove this organization from your list?')) {
- orgStore.removeOrganization(orgId)
- if (currentOrgId.value === orgId) {
+ orgStore.removeOrganization(org.id)
+ if (currentOrgSlug.value === org.slug) {
router.push('/')
}
}
@@ -63,8 +63,8 @@ async function copyOrgId(e: Event, orgId: string) {
<div
v-for="org in orgStore.organizations"
:key="org.id"
- :class="['org-item', { active: currentOrgId === org.id }]"
- @click="selectOrg(org.id)"
+ :class="['org-item', { active: currentOrgSlug === org.slug }]"
+ @click="selectOrg(org.slug)"
>
<div class="org-avatar">{{ org.name.charAt(0).toUpperCase() }}</div>
<div class="org-info">
@@ -85,7 +85,7 @@ async function copyOrgId(e: Event, orgId: string) {
<button
class="action-btn action-btn-danger"
title="Remove"
- @click="removeOrg($event, org.id)"
+ @click="removeOrg($event, org)"
>
<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M18 6L6 18M6 6l12 12"/>
diff --git a/src/router/index.ts b/src/router/index.ts
index b1428ae..cceaf85 100644
--- a/src/router/index.ts
+++ b/src/router/index.ts
@@ -16,32 +16,32 @@ const router = createRouter({
component: HomeView,
},
{
- path: '/org/:orgId',
+ path: '/org/:orgSlug',
name: 'org',
component: HomeView,
},
{
- path: '/org/:orgId/app/:appId',
+ path: '/org/:orgSlug/app/:appSlug',
name: 'app-detail',
component: AppDetailView,
},
{
- path: '/org/:orgId/app/:appId/add-deeplink',
+ path: '/org/:orgSlug/app/:appSlug/add-deeplink',
name: 'add-deeplink',
component: AddDeeplinkView,
},
{
- path: '/org/:orgId/app/:appId/deeplink/:deeplinkId/edit',
+ path: '/org/:orgSlug/app/:appSlug/deeplink/:deeplinkId/edit',
name: 'edit-deeplink',
component: AddDeeplinkView,
},
{
- path: '/org/:orgId/add-app',
+ path: '/org/:orgSlug/add-app',
name: 'add-app',
component: AddAppView,
},
{
- path: '/org/:orgId/app/:appId/edit-app',
+ path: '/org/:orgSlug/app/:appSlug/edit-app',
name: 'edit-app',
component: AddAppView,
},
diff --git a/src/stores/organizations.ts b/src/stores/organizations.ts
index accf31d..d739e10 100644
--- a/src/stores/organizations.ts
+++ b/src/stores/organizations.ts
@@ -20,7 +20,7 @@ function saveToStorage(orgs: Organization[]) {
export const useOrganizationsStore = defineStore('organizations', () => {
const organizations = ref<Organization[]>(loadFromStorage())
- const currentOrgId = ref<string | null>(null)
+ const currentOrgSlug = ref<string | null>(null)
const apps = ref<App[]>([])
const appsLoading = ref(false)
const appsError = ref<string | null>(null)
@@ -33,16 +33,17 @@ export const useOrganizationsStore = defineStore('organizations', () => {
}
function removeOrganization(orgId: string) {
+ const removed = organizations.value.find(o => o.id === orgId)
organizations.value = organizations.value.filter(o => o.id !== orgId)
saveToStorage(organizations.value)
- if (currentOrgId.value === orgId) {
- currentOrgId.value = null
+ if (removed && currentOrgSlug.value === removed.slug) {
+ currentOrgSlug.value = null
apps.value = []
}
}
- function setCurrentOrg(orgId: string | null) {
- currentOrgId.value = orgId
+ function setCurrentOrg(slug: string | null) {
+ currentOrgSlug.value = slug
}
function setApps(newApps: App[]) {
@@ -88,7 +89,7 @@ export const useOrganizationsStore = defineStore('organizations', () => {
return {
organizations,
- currentOrgId,
+ currentOrgSlug,
apps,
appsLoading,
appsError,
diff --git a/src/types/index.ts b/src/types/index.ts
index 7958c25..b091138 100644
--- a/src/types/index.ts
+++ b/src/types/index.ts
@@ -12,6 +12,7 @@ export interface Environment {
export interface App {
id: string
name: string
+ slug: string
organizationId: string
deeplinksCount: number
environments: Environment[]
diff --git a/src/views/AddAppView.vue b/src/views/AddAppView.vue
index 2152ced..388213a 100644
--- a/src/views/AddAppView.vue
+++ b/src/views/AddAppView.vue
@@ -2,7 +2,7 @@
import {ref, onMounted, computed} from 'vue'
import {useRoute, useRouter} from 'vue-router'
import {useOrganizationsStore} from '@/stores/organizations'
-import {createApp, deleteApp, getApp, updateApp} from '@/api/client'
+import {createApp, deleteApp, getAppBySlug, updateApp, getOrganizationBySlug} from '@/api/client'
import type {Environment} from '@/types'
import AppLayout from '@/components/AppLayout.vue'
import EnvironmentEditor from '@/components/EnvironmentEditor.vue'
@@ -11,9 +11,12 @@ const route = useRoute()
const router = useRouter()
const orgStore = useOrganizationsStore()
-const orgId = route.params.orgId as string
-const appId = route.params.appId as string | undefined
-const isEdit = computed(() => !!appId)
+const orgSlug = route.params.orgSlug as string
+const appSlug = route.params.appSlug as string | undefined
+const isEdit = computed(() => !!appSlug)
+
+const orgId = ref<string>('')
+const appId = ref<string>('')
const name = ref('')
const environments = ref<Environment[]>([{name: '', scheme: ''}])
@@ -22,22 +25,32 @@ const deleting = ref(false)
const error = ref<string | null>(null)
const initialLoading = ref(false)
-const org = computed(() => orgStore.organizations.find(o => o.id === orgId))
+const org = computed(() => orgStore.organizations.find(o => o.slug === orgSlug))
+
+async function resolveOrgId(): Promise<string> {
+ const cached = orgStore.organizations.find(o => o.slug === orgSlug)
+ if (cached) return cached.id
+ const fetched = await getOrganizationBySlug(orgSlug)
+ orgStore.addOrganization(fetched)
+ return fetched.id
+}
onMounted(async () => {
- if (isEdit.value && appId) {
- initialLoading.value = true
- try {
- const app = await getApp(orgId, appId)
+ initialLoading.value = true
+ try {
+ orgId.value = await resolveOrgId()
+ if (isEdit.value && appSlug) {
+ const app = await getAppBySlug(orgSlug, appSlug)
+ appId.value = app.id
name.value = app.name
environments.value = app.environments.length > 0
? app.environments.map(e => ({...e}))
: [{name: '', scheme: ''}]
- } catch {
- error.value = 'Failed to load app details'
- } finally {
- initialLoading.value = false
}
+ } catch {
+ error.value = 'Failed to load app details'
+ } finally {
+ initialLoading.value = false
}
})
@@ -59,20 +72,20 @@ async function handleSubmit() {
error.value = null
try {
- if (isEdit.value && appId) {
- const updated = await updateApp(orgId, appId, {
+ if (isEdit.value && appId.value) {
+ const updated = await updateApp(orgId.value, appId.value, {
name: name.value.trim(),
environments: envsMap,
})
orgStore.addApp(updated)
- router.push(`/org/${orgId}/app/${appId}`)
+ router.push(`/org/${orgSlug}/app/${updated.slug}`)
} else {
- const app = await createApp(orgId, {
+ const app = await createApp(orgId.value, {
name: name.value.trim(),
environments: envsMap,
})
orgStore.addApp(app)
- router.push(`/org/${orgId}/app/${app.id}`)
+ router.push(`/org/${orgSlug}/app/${app.slug}`)
}
} catch (e: unknown) {
if (e instanceof Error) {
@@ -87,18 +100,18 @@ async function handleSubmit() {
}
const backUrl = computed(() =>
- isEdit.value && appId ? `/org/${orgId}/app/${appId}` : `/org/${orgId}`
+ isEdit.value && appSlug ? `/org/${orgSlug}/app/${appSlug}` : `/org/${orgSlug}`
)
async function handleDelete() {
- if (!appId) return
+ if (!appId.value) return
if (!confirm('Delete this app? This cannot be undone.')) return
deleting.value = true
error.value = null
try {
- await deleteApp(orgId, appId)
- orgStore.removeApp(appId)
- router.push(`/org/${orgId}`)
+ await deleteApp(orgId.value, appId.value)
+ orgStore.removeApp(appId.value)
+ router.push(`/org/${orgSlug}`)
} catch (e: unknown) {
error.value = e instanceof Error ? e.message : 'Failed to delete app'
} finally {
diff --git a/src/views/AddDeeplinkView.vue b/src/views/AddDeeplinkView.vue
index 89a4693..a879b61 100644
--- a/src/views/AddDeeplinkView.vue
+++ b/src/views/AddDeeplinkView.vue
@@ -2,7 +2,7 @@
import { ref, onMounted, computed } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { useOrganizationsStore } from '@/stores/organizations'
-import { createDeeplink, getDeeplink, updateDeeplink, getApp } from '@/api/client'
+import { createDeeplink, getDeeplink, updateDeeplink, getAppBySlug, getOrganizationBySlug } from '@/api/client'
import type { QueryParamType } from '@/types'
import AppLayout from '@/components/AppLayout.vue'
import QueryParamEditor from '@/components/QueryParamEditor.vue'
@@ -11,11 +11,14 @@ const route = useRoute()
const router = useRouter()
const orgStore = useOrganizationsStore()
-const orgId = route.params.orgId as string
-const appId = route.params.appId as string
+const orgSlug = route.params.orgSlug as string
+const appSlug = route.params.appSlug as string
const deeplinkId = route.params.deeplinkId as string | undefined
const isEdit = computed(() => !!deeplinkId)
+const orgId = ref<string>('')
+const appId = ref<string>('')
+
// Form fields
const name = ref('')
const description = ref('')
@@ -28,9 +31,17 @@ const loading = ref(false)
const error = ref<string | null>(null)
const initialLoading = ref(false)
-const org = computed(() => orgStore.organizations.find(o => o.id === orgId))
+const org = computed(() => orgStore.organizations.find(o => o.slug === orgSlug))
const appName = ref('')
+async function resolveOrgId(): Promise<string> {
+ const cached = orgStore.organizations.find(o => o.slug === orgSlug)
+ if (cached) return cached.id
+ const fetched = await getOrganizationBySlug(orgSlug)
+ orgStore.addOrganization(fetched)
+ return fetched.id
+}
+
const importUri = ref('')
const importError = ref<string | null>(null)
@@ -107,12 +118,13 @@ function parseUri() {
onMounted(async () => {
initialLoading.value = true
try {
- // Load app name
- const app = await getApp(orgId, appId)
+ orgId.value = await resolveOrgId()
+ const app = await getAppBySlug(orgSlug, appSlug)
+ appId.value = app.id
appName.value = app.name
if (isEdit.value && deeplinkId) {
- const dl = await getDeeplink(orgId, appId, deeplinkId)
+ const dl = await getDeeplink(orgId.value, appId.value, deeplinkId)
name.value = dl.name ?? ''
description.value = dl.description ?? ''
host.value = dl.host ?? ''
@@ -158,11 +170,11 @@ async function handleSubmit() {
try {
if (isEdit.value && deeplinkId) {
- await updateDeeplink(orgId, appId, deeplinkId, payload)
+ await updateDeeplink(orgId.value, appId.value, deeplinkId, payload)
} else {
- await createDeeplink(orgId, appId, payload)
+ await createDeeplink(orgId.value, appId.value, payload)
}
- router.push(`/org/${orgId}/app/${appId}`)
+ router.push(`/org/${orgSlug}/app/${appSlug}`)
} catch (e: unknown) {
error.value = e instanceof Error ? e.message : 'Failed to save deeplink'
} finally {
@@ -170,7 +182,7 @@ async function handleSubmit() {
}
}
-const backUrl = computed(() => `/org/${orgId}/app/${appId}`)
+const backUrl = computed(() => `/org/${orgSlug}/app/${appSlug}`)
// Live URI preview (using placeholder scheme)
const previewUri = computed(() => {
diff --git a/src/views/AddOrgView.vue b/src/views/AddOrgView.vue
index 64d62fd..8aba8cf 100644
--- a/src/views/AddOrgView.vue
+++ b/src/views/AddOrgView.vue
@@ -30,8 +30,9 @@ async function handleCreate() {
try {
const org = await createOrganization(createName.value.trim())
orgStore.addOrganization(org)
- router.push(`/org/${org.id}`)
+ router.push(`/org/${org.slug}`)
} catch (e: unknown) {
+ console.log(e)
createError.value =
e instanceof Error ? e.message : 'Failed to create organization'
} finally {
@@ -49,7 +50,7 @@ async function handleJoin() {
try {
const org = await getOrganization(joinId.value.trim())
orgStore.addOrganization(org)
- router.push(`/org/${org.id}`)
+ router.push(`/org/${org.slug}`)
} catch (e: unknown) {
joinError.value =
e instanceof Error ? e.message : 'Organization not found'
diff --git a/src/views/AppDetailView.vue b/src/views/AppDetailView.vue
index 2c4f662..a23e6c4 100644
--- a/src/views/AppDetailView.vue
+++ b/src/views/AppDetailView.vue
@@ -3,7 +3,7 @@ import { ref, onMounted, computed, watch } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { useOrganizationsStore } from '@/stores/organizations'
import { useHistoryStore } from '@/stores/history'
-import { getApp, getDeeplinks, deleteDeeplink } from '@/api/client'
+import { getAppBySlug, getDeeplinks, deleteDeeplink, getOrganizationBySlug } from '@/api/client'
import type { DeeplinkTemplate, App, Environment } from '@/types'
import AppLayout from '@/components/AppLayout.vue'
import DeeplinkCard from '@/components/DeeplinkCard.vue'
@@ -14,8 +14,10 @@ const router = useRouter()
const orgStore = useOrganizationsStore()
const historyStore = useHistoryStore()
-const orgId = route.params.orgId as string
-const appId = route.params.appId as string
+const orgSlug = route.params.orgSlug as string
+const appSlug = route.params.appSlug as string
+
+const orgId = ref<string>('')
const app = ref<App | null>(null)
const deeplinks = ref<DeeplinkTemplate[]>([])
@@ -34,16 +36,24 @@ const launchEnv = computed<Environment | null>(
() => launchEnvOverride.value ?? selectedEnv.value
)
-const org = computed(() => orgStore.organizations.find(o => o.id === orgId))
+const org = computed(() => orgStore.organizations.find(o => o.slug === orgSlug))
+
+async function resolveOrgId(): Promise<string> {
+ const cached = orgStore.organizations.find(o => o.slug === orgSlug)
+ if (cached) return cached.id
+ const fetched = await getOrganizationBySlug(orgSlug)
+ orgStore.addOrganization(fetched)
+ return fetched.id
+}
async function loadData() {
loading.value = true
error.value = null
try {
- const [appData, deeplinksData] = await Promise.all([
- getApp(orgId, appId),
- getDeeplinks(orgId, appId),
- ])
+ const id = await resolveOrgId()
+ orgId.value = id
+ const appData = await getAppBySlug(orgSlug, appSlug)
+ const deeplinksData = await getDeeplinks(id, appData.id)
app.value = appData
deeplinks.value = deeplinksData
} catch (e: unknown) {
@@ -78,20 +88,19 @@ watch(() => route.query.launchEntry, (v) => {
})
async function handleDeleteDeeplink(deeplinkId: string) {
+ if (!app.value) return
if (!confirm('Delete this deeplink? This cannot be undone.')) return
try {
- await deleteDeeplink(orgId, appId, deeplinkId)
+ await deleteDeeplink(orgId.value, app.value.id, deeplinkId)
deeplinks.value = deeplinks.value.filter(d => d.id !== deeplinkId)
- if (app.value) {
- app.value = { ...app.value, deeplinksCount: app.value.deeplinksCount - 1 }
- }
+ app.value = { ...app.value, deeplinksCount: app.value.deeplinksCount - 1 }
} catch {
alert('Failed to delete deeplink')
}
}
function handleEditDeeplink(deeplink: DeeplinkTemplate) {
- router.push(`/org/${orgId}/app/${appId}/deeplink/${deeplink.id}/edit`)
+ router.push(`/org/${orgSlug}/app/${appSlug}/deeplink/${deeplink.id}/edit`)
}
function handleLaunchDeeplink(deeplink: DeeplinkTemplate) {
@@ -126,7 +135,7 @@ function closeLaunchModal() {
<template v-else-if="app">
<!-- Breadcrumb -->
<div class="breadcrumb">
- <RouterLink :to="`/org/${orgId}`" class="breadcrumb-link">
+ <RouterLink :to="`/org/${orgSlug}`" class="breadcrumb-link">
{{ org?.name || 'Org' }}
</RouterLink>
<span class="breadcrumb-sep">›</span>
@@ -150,7 +159,7 @@ function closeLaunchModal() {
</div>
<div class="header-actions">
<RouterLink
- :to="`/org/${orgId}/app/${appId}/edit-app`"
+ :to="`/org/${orgSlug}/app/${appSlug}/edit-app`"
class="btn btn-secondary"
title="Edit app"
>
@@ -161,7 +170,7 @@ function closeLaunchModal() {
Edit
</RouterLink>
<RouterLink
- :to="`/org/${orgId}/app/${appId}/add-deeplink`"
+ :to="`/org/${orgSlug}/app/${appSlug}/add-deeplink`"
class="btn btn-primary"
>
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5">
@@ -178,7 +187,7 @@ function closeLaunchModal() {
<h3>No deeplinks yet</h3>
<p>Add your first deeplink template to start launching.</p>
<RouterLink
- :to="`/org/${orgId}/app/${appId}/add-deeplink`"
+ :to="`/org/${orgSlug}/app/${appSlug}/add-deeplink`"
class="btn btn-primary"
style="margin-top: 16px; display: inline-flex;"
>
@@ -192,8 +201,6 @@ function closeLaunchModal() {
v-for="deeplink in deeplinks"
:key="deeplink.id"
:deeplink="deeplink"
- :orgId="orgId"
- :appId="appId"
:environment="selectedEnv"
@launch="handleLaunchDeeplink"
/>
diff --git a/src/views/HomeView.vue b/src/views/HomeView.vue
index 2653d85..1eda49d 100644
--- a/src/views/HomeView.vue
+++ b/src/views/HomeView.vue
@@ -1,25 +1,29 @@
<script setup lang="ts">
import {watch, onMounted} from 'vue'
-import {useRoute, useRouter} from 'vue-router'
+import {useRoute} from 'vue-router'
import {useOrganizationsStore} from '@/stores/organizations'
-import {getApps} from '@/api/client'
+import {getApps, getOrganizationBySlug} from '@/api/client'
import AppLayout from '@/components/AppLayout.vue'
import AppCard from '@/components/AppCard.vue'
const route = useRoute()
-const router = useRouter()
const orgStore = useOrganizationsStore()
-const orgId = () => route.params.orgId as string | undefined
+const orgSlug = () => route.params.orgSlug as string | undefined
const currentOrg = () =>
- orgId() ? orgStore.organizations.find(o => o.id === orgId()) : null
+ orgSlug() ? orgStore.organizations.find(o => o.slug === orgSlug()) : null
-async function loadApps(id: string) {
+async function loadAppsBySlug(slug: string) {
orgStore.setAppsLoading(true)
orgStore.setAppsError(null)
try {
- const apps = await getApps(id)
+ let org = orgStore.organizations.find(o => o.slug === slug)
+ if (!org) {
+ org = await getOrganizationBySlug(slug)
+ orgStore.addOrganization(org)
+ }
+ const apps = await getApps(org.id)
orgStore.setApps(apps)
} catch (e: unknown) {
orgStore.setAppsError(
@@ -31,11 +35,11 @@ async function loadApps(id: string) {
}
watch(
- () => route.params.orgId,
- (id) => {
- if (id) {
- orgStore.setCurrentOrg(id as string)
- loadApps(id as string)
+ () => route.params.orgSlug,
+ (slug) => {
+ if (slug) {
+ orgStore.setCurrentOrg(slug as string)
+ loadAppsBySlug(slug as string)
} else {
orgStore.setCurrentOrg(null)
orgStore.setApps([])
@@ -44,10 +48,10 @@ watch(
)
onMounted(() => {
- const id = orgId()
- if (id) {
- orgStore.setCurrentOrg(id)
- loadApps(id)
+ const slug = orgSlug()
+ if (slug) {
+ orgStore.setCurrentOrg(slug)
+ loadAppsBySlug(slug)
}
})
@@ -57,7 +61,7 @@ onMounted(() => {
<AppLayout>
<div class="home-view">
<!-- No org selected -->
- <div v-if="!orgId()" class="empty-state">
+ <div v-if="!orgSlug()" class="empty-state">
<div class="empty-state-icon">🤿</div>
<h3>Welcome to Diver</h3>
<p>Select or add an organization from the sidebar to get started.</p>
@@ -81,7 +85,7 @@ onMounted(() => {
<div class="page-subtitle">Apps</div>
</div>
<RouterLink
- :to="`/org/${orgId()}/add-app`"
+ :to="`/org/${orgSlug()}/add-app`"
class="btn btn-primary"
>
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5">
@@ -108,7 +112,7 @@ onMounted(() => {
<h3>No apps yet</h3>
<p>Add your first app to start managing deeplinks.</p>
<RouterLink
- :to="`/org/${orgId()}/add-app`"
+ :to="`/org/${orgSlug()}/add-app`"
class="btn btn-primary"
style="margin-top: 16px; display: inline-flex;"
>
@@ -122,7 +126,7 @@ onMounted(() => {
v-for="app in orgStore.apps"
:key="app.id"
:app="app"
- :orgId="orgId()!"
+ :orgSlug="orgSlug()!"
/>
</div>
</template>
diff --git a/src/views/LaunchHistoryView.vue b/src/views/LaunchHistoryView.vue
index 59fa3e4..bec70c5 100644
--- a/src/views/LaunchHistoryView.vue
+++ b/src/views/LaunchHistoryView.vue
@@ -2,17 +2,24 @@
import {computed} from 'vue'
import {useRouter} from 'vue-router'
import {useHistoryStore} from '@/stores/history'
+import {useOrganizationsStore} from '@/stores/organizations'
import AppLayout from '@/components/AppLayout.vue'
import type {LaunchHistoryEntry} from '@/types'
const router = useRouter()
const historyStore = useHistoryStore()
+const orgStore = useOrganizationsStore()
function openEntry(entry: LaunchHistoryEntry) {
if (entry.deeplink && entry.app && entry.environmentSnapshot && entry.orgId) {
+ const org = orgStore.organizations.find(o => o.id === entry.orgId)
+ if (!org) {
+ window.open(entry.uri)
+ return
+ }
router.push({
name: 'app-detail',
- params: {orgId: entry.orgId, appId: entry.app.id},
+ params: {orgSlug: org.slug, appSlug: entry.app.slug},
query: {launchEntry: entry.id},
})
} else {