diff --git a/frontend/src/components/projects/ProjectPageMarkdown.vue b/frontend/src/components/projects/ProjectPageMarkdown.vue
index 80a9cfd5..41b724e6 100644
--- a/frontend/src/components/projects/ProjectPageMarkdown.vue
+++ b/frontend/src/components/projects/ProjectPageMarkdown.vue
@@ -3,17 +3,23 @@ import type { ExtendedProjectPage, HangarProject, HangarProjectPage } from "~/ty
const props = defineProps<{
project?: HangarProject;
+ page?: ExtendedProjectPage;
mainPage: boolean;
}>();
-const route = useRoute("user-project-pages-all");
+const route = useRoute("user-project-pages-page");
const router = useRouter();
const updateProjectPages = inject<(pages: HangarProjectPage[]) => void>("updateProjectPages");
-const { editingPage, changeEditingPage, page, savePage, deletePage } = await useProjectPage(route, router, props.project, props.mainPage);
+const { editingPage, changeEditingPage, savePage, deletePage } = useProjectPage(
+ route,
+ router,
+ props.project,
+ props.mainPage ? props.project?.mainPage : props.page
+);
if (!props.mainPage) {
- useHead(useSeo(page.value?.name + " | " + props.project?.name, props.project?.description, route, props.project?.avatarUrl));
+ useHead(useSeo(props.page?.name + " | " + props.project?.name, props.project?.description, route, props.project?.avatarUrl));
}
async function deletePageAndUpdateProject() {
@@ -29,22 +35,10 @@ async function deletePageAndUpdateProject() {
}
defineSlots<{
- default: (props: {
- page?: ExtendedProjectPage | null;
- editingPage: boolean;
- changeEditingPage: (editing: boolean) => void;
- savePage: (content: string) => void;
- deletePage: () => void;
- }) => any;
+ default: (props: { editingPage: boolean; changeEditingPage: (editing: boolean) => void; savePage: (content: string) => void; deletePage: () => void }) => any;
}>();
-
+
diff --git a/frontend/src/composables/useDataLoader.ts b/frontend/src/composables/useDataLoader.ts
index a95733cc..76787fbc 100644
--- a/frontend/src/composables/useDataLoader.ts
+++ b/frontend/src/composables/useDataLoader.ts
@@ -1,7 +1,7 @@
import type { RouteLocationNormalized } from "vue-router";
-type dataLoaders = "user" | "project" | "version" | "organization";
-type routeParams = "user" | "project" | "version" | "organization";
+type dataLoaders = "user" | "project" | "version" | "organization" | "page";
+type routeParams = "user" | "project" | "version" | "organization" | "page";
// TODO check every handling of the reject stuff (for both composables)
diff --git a/frontend/src/composables/useOpenProjectPages.ts b/frontend/src/composables/useOpenProjectPages.ts
index cb1a14a0..a39fee46 100644
--- a/frontend/src/composables/useOpenProjectPages.ts
+++ b/frontend/src/composables/useOpenProjectPages.ts
@@ -1,7 +1,7 @@
import type { HangarProject } from "~/types/backend";
import type { RouteLocationTyped, RouteMapGeneric } from "vue-router";
-export function useOpenProjectPages(route: RouteLocationTyped, project?: HangarProject) {
+export function useOpenProjectPages(route: RouteLocationTyped, project?: HangarProject) {
const open = ref([]);
watch(
diff --git a/frontend/src/composables/useProjectPage.ts b/frontend/src/composables/useProjectPage.ts
index a7dcddfb..84c081e5 100644
--- a/frontend/src/composables/useProjectPage.ts
+++ b/frontend/src/composables/useProjectPage.ts
@@ -1,14 +1,8 @@
-import type { HangarProject } from "~/types/backend";
+import type { ExtendedProjectPage, HangarProject } from "~/types/backend";
import type { Router } from "vue-router";
import type { RouteLocationNormalized } from "vue-router/auto";
-export async function useProjectPage(route: RouteLocationNormalized<"user-project-pages-all">, router: Router, project?: HangarProject, mainPage?: boolean) {
- const page = mainPage ? computed(() => project?.mainPage) : usePage(() => ({ project: route.params.project, path: route.params.all?.toString() })).page;
- // TODO fix this
- // if (!page?.value) {
- // throw useErrorRedirect(404, "Not found");
- // }
-
+export function useProjectPage(route: RouteLocationNormalized<"user-project-pages-page">, router: Router, project?: HangarProject, page?: ExtendedProjectPage) {
const editingPage = ref(false);
// Helper setter function, v-model cannot directly edit from inside a slot.
@@ -17,21 +11,21 @@ export async function useProjectPage(route: RouteLocationNormalized<"user-projec
}
async function savePage(content: string) {
- if (!page?.value) return;
- await useInternalApi(`pages/save/${project?.id}/${page.value?.id}`, "post", {
+ if (!page) return;
+ await useInternalApi(`pages/save/${project?.id}/${page?.id}`, "post", {
content,
}).catch((e) => handleRequestError(e, "page.new.error.save"));
- if (page.value && "contents" in page.value) {
- page.value.contents = content;
+ if (page && "contents" in page) {
+ page.contents = content;
}
editingPage.value = false;
}
async function deletePage() {
- if (!page?.value) return;
- await useInternalApi(`pages/delete/${project?.id}/${page.value?.id}`, "post").catch((e) => handleRequestError(e, "page.new.error.save"));
+ if (!page) return;
+ await useInternalApi(`pages/delete/${project?.id}/${page?.id}`, "post").catch((e) => handleRequestError(e, "page.new.error.save"));
await router.replace(`/${route.params.user}/${route.params.project}`);
}
- return { editingPage, changeEditingPage, page, savePage, deletePage };
+ return { editingPage, changeEditingPage, savePage, deletePage };
}
diff --git a/frontend/src/middleware/data.global.ts b/frontend/src/middleware/data.global.ts
index 44884a62..fd347c8d 100644
--- a/frontend/src/middleware/data.global.ts
+++ b/frontend/src/middleware/data.global.ts
@@ -1,4 +1,4 @@
-import type { HangarOrganization, HangarProject, HangarVersion, User } from "~/types/backend";
+import type { ExtendedProjectPage, HangarOrganization, HangarProject, HangarVersion, User } from "~/types/backend";
import { useDataLoader } from "~/composables/useDataLoader";
import { isAxiosError } from "axios";
@@ -44,6 +44,20 @@ export default defineNuxtRouteMiddleware(async (to, from) => {
promises
);
+ const { loader: pageLoader, data: page } = useDataLoader("page");
+ const pageName = pageLoader(
+ "page",
+ to,
+ from,
+ async (pagePath) => {
+ if ("project" in to.params) {
+ return useInternalApi(`pages/page/${to.params.project}/` + pagePath.toString().replaceAll(",", "/"));
+ }
+ throw createError({ statusCode: 500, statusMessage: "No project param?!" });
+ },
+ promises
+ ) as string[] | undefined;
+
if (import.meta.server && promises?.length) {
try {
await Promise.all(promises);
@@ -60,17 +74,23 @@ export default defineNuxtRouteMiddleware(async (to, from) => {
let newPath = to.fullPath;
if (userName) {
if (user.value && user.value.name !== userName) {
- newPath = newPath.replace(userName, user.value?.name);
+ newPath = newPath.replace(userName, user.value.name);
}
}
if (projectName) {
if (project.value && project.value.name !== projectName) {
- newPath = newPath.replace(projectName, project.value?.name);
+ newPath = newPath.replace(projectName, project.value.name);
}
}
if (versionName) {
if (version.value && version.value.name !== versionName) {
- newPath = newPath.replace(versionName, version.value?.name);
+ newPath = newPath.replace(versionName, version.value.name);
+ }
+ }
+ if (pageName) {
+ const pageSlug = pageName.join("/");
+ if (page.value && page.value.slug !== pageSlug) {
+ newPath = newPath.replace(pageSlug, page.value.slug);
}
}
if (newPath != to.fullPath) {
diff --git a/frontend/src/pages/[user]/[project]/index.vue b/frontend/src/pages/[user]/[project]/index.vue
index 8e706e3f..6fa27ff0 100644
--- a/frontend/src/pages/[user]/[project]/index.vue
+++ b/frontend/src/pages/[user]/[project]/index.vue
@@ -9,7 +9,7 @@ const props = defineProps<{
const config = useConfig();
const i18n = useI18n();
-const route = useRoute("user-project-pages-all");
+const route = useRoute("user-project-pages-page");
const openProjectPages = useOpenProjectPages(route, props.project);
const sponsors = ref(props.project?.settings?.sponsors);
@@ -65,12 +65,12 @@ useHead(
-
-
+
+
-
+
-
+
diff --git a/frontend/src/pages/[user]/[project]/pages/[...all].vue b/frontend/src/pages/[user]/[project]/pages/[...page].vue
similarity index 77%
rename from frontend/src/pages/[user]/[project]/pages/[...all].vue
rename to frontend/src/pages/[user]/[project]/pages/[...page].vue
index ef6c8ef5..7234902a 100644
--- a/frontend/src/pages/[user]/[project]/pages/[...all].vue
+++ b/frontend/src/pages/[user]/[project]/pages/[...page].vue
@@ -1,12 +1,19 @@