diff --git a/.claude/TASKS.md b/.claude/TASKS.md index f94965b..ffdbfc0 100644 --- a/.claude/TASKS.md +++ b/.claude/TASKS.md @@ -71,7 +71,7 @@ Use GitHub-style checkboxes to mark task completion: - [x] Configure GraphQL schema for ACF fields - [x] Test GraphQL queries for all content types - [x] Set up GraphQL authentication and permissions -- [ ] Customize MediaItem GraphQL type to include center (x/y) fields +- [x] Customize MediaItem GraphQL type to include center (x/y) fields --- @@ -157,7 +157,7 @@ Use GitHub-style checkboxes to mark task completion: ### Content Features - [x] Implement image uploads with point-of-interest cropping -- [ ] Implement virtual pages (redirect to first child) +- [x] Implement virtual pages (redirect to first child) - [ ] Create automated URL redirect system - [ ] Build content search and filtering - [ ] Create content categorization system diff --git a/wp-content/themes/ccat/acf-json/group_post_page.json b/wp-content/themes/ccat/acf-json/group_post_page.json index f875378..1bba115 100644 --- a/wp-content/themes/ccat/acf-json/group_post_page.json +++ b/wp-content/themes/ccat/acf-json/group_post_page.json @@ -62,5 +62,5 @@ "graphql_types": "", "acfe_meta": "", "acfe_note": "", - "modified": 1757959232 -} \ No newline at end of file + "modified": 1758829149 +} diff --git a/wp-content/themes/ccat/app/components/nodes/ThePage.fragment.gql b/wp-content/themes/ccat/app/components/nodes/ThePage.fragment.gql index cab411c..0896a39 100644 --- a/wp-content/themes/ccat/app/components/nodes/ThePage.fragment.gql +++ b/wp-content/themes/ccat/app/components/nodes/ThePage.fragment.gql @@ -1,5 +1,13 @@ fragment ThePage on Page { title + template { + __typename + } + children { + nodes { + uri + } + } groupPostPage { sections { ...TheSection diff --git a/wp-content/themes/ccat/app/components/nodes/ThePage.vue b/wp-content/themes/ccat/app/components/nodes/ThePage.vue index b953ec5..29729db 100644 --- a/wp-content/themes/ccat/app/components/nodes/ThePage.vue +++ b/wp-content/themes/ccat/app/components/nodes/ThePage.vue @@ -2,6 +2,11 @@ import type { ThePageFragment } from "#graphql-operations"; const props = defineProps(); + +if (props.template?.__typename === "Template_VirtualPage") { + await navigateTo(props.children?.nodes[0]?.uri || "/"); +} + useSeoMeta({ title: props.title }); diff --git a/wp-content/themes/ccat/app/composables/useSiteOptions.ts b/wp-content/themes/ccat/app/composables/useSiteOptions.ts index be98340..934fca1 100644 --- a/wp-content/themes/ccat/app/composables/useSiteOptions.ts +++ b/wp-content/themes/ccat/app/composables/useSiteOptions.ts @@ -1,7 +1,13 @@ export async function useSiteOptions() { - const { data } = await useAsyncGraphqlQuery("siteOptions", {}, { graphqlCaching: { client: true } }); - if (data.value?.errors?.length || !data.value?.data.siteOptions?.groupCcat) { - throw createError({ statusCode: 500, message: "Erreur lors de la récupération des options du site" }); + const { data, error } = await useAsyncGraphqlQuery("siteOptions", {}, { graphqlCaching: { client: true } }); + if (error.value) { + throw createError({ statusCode: 500, statusMessage: "Erreur interne", message: error.value.message }); + } + if (data.value?.errors.length) { + throw createError({ statusCode: 500, statusMessage: "Erreur interne", message: data.value.errors.map((error) => error.message).join("\n") }); + } + if (!data.value?.data.siteOptions?.groupCcat) { + throw createError({ statusCode: 500, statusMessage: "Erreur interne", message: "Options du site invalides." }); } return { ...data.value?.data.siteOptions?.groupCcat }; } diff --git a/wp-content/themes/ccat/functions.php b/wp-content/themes/ccat/functions.php index e1dd48f..2c50db6 100644 --- a/wp-content/themes/ccat/functions.php +++ b/wp-content/themes/ccat/functions.php @@ -5,6 +5,7 @@ // Core require_once __DIR__ . '/includes/core/sections.php'; require_once __DIR__ . '/includes/core/theme-setup.php'; +require_once __DIR__ . '/includes/core/virtual-page.php'; // Custom Post Types require_once __DIR__ . '/includes/cpt/contributor.php'; diff --git a/wp-content/themes/ccat/includes/core/virtual-page.php b/wp-content/themes/ccat/includes/core/virtual-page.php new file mode 100644 index 0000000..a773ad3 --- /dev/null +++ b/wp-content/themes/ccat/includes/core/virtual-page.php @@ -0,0 +1,18 @@ +fieldName === 'path' ) { + $menu_item = wp_setup_nav_menu_item( get_post( $source->databaseId ) ); + if ( $menu_item->object === 'page' && ccat_is_virtual_page( $menu_item->object_id ) ) { + return '#'; + } + } + return $result; +} diff --git a/wp-content/themes/ccat/includes/graphql/breadcrumbs.php b/wp-content/themes/ccat/includes/graphql/breadcrumbs.php index 2483c29..835612b 100644 --- a/wp-content/themes/ccat/includes/graphql/breadcrumbs.php +++ b/wp-content/themes/ccat/includes/graphql/breadcrumbs.php @@ -49,102 +49,77 @@ function ccat_register_breadcrumb_graphql_fields() { // Helper: Get breadcrumbs for a given node function ccat_get_breadcrumbs( $node ) { + if ( $node instanceof \WPGraphQL\Model\Post ) { + return ccat_get_post_breadcrumbs( $node->databaseId ); + } + if ( $node instanceof \WPGraphQL\Model\Term ) { + return ccat_get_term_breadcrumbs( $node->databaseId ); + } + return array(); +} + +// Helper: Get breadcrumbs for a given post ID +function ccat_get_post_breadcrumbs( $post_id ) { $breadcrumbs = array(); - if ( ! $node ) { + + $is_front_page = get_option( 'show_on_front' ) === 'page' && (int) get_option( 'page_on_front' ) === $post_id; + if ( $is_front_page ) { return $breadcrumbs; } - if ( $node instanceof \WPGraphQL\Model\Post ) { - $post = get_post( $node->databaseId ); - if ( $post ) { - $breadcrumbs = ccat_get_post_breadcrumbs( $post ); - $breadcrumbs[] = array( - 'label' => get_the_title( $post->ID ), - 'to' => null, - ); - } - } elseif ( $node instanceof \WPGraphQL\Model\Term ) { - $term = get_term( $node->databaseId ); - if ( $term && ! is_wp_error( $term ) ) { - $breadcrumbs = ccat_get_term_breadcrumbs( $term ); - $breadcrumbs[] = array( - 'label' => $term->name, - 'to' => null, - ); - } - } - return $breadcrumbs; -} -// Helper: Get breadcrumbs for a given post -function ccat_get_post_breadcrumbs( WP_Post $post ) { - $breadcrumbs = array(); - $is_front_page = get_option( 'show_on_front' ) === 'page' && (int) get_option( 'page_on_front' ) === $post->ID; - if ( $is_front_page ) { - return $breadcrumbs; // No breadcrumbs for the front page - } else { + $breadcrumbs[] = array( + 'label' => 'Accueil', + 'to' => '/', + ); + + $post_type = get_post_type( $post_id ); + $ancestor_ids = get_post_ancestors( $post_type === 'page' ? $post_id : get_option( "page_for_$post_type" ) ); + $ancestor_ids = array_reverse( $ancestor_ids ); + foreach ( $ancestor_ids as $ancestor_id ) { $breadcrumbs[] = array( - 'label' => 'Accueil', - 'to' => '/', + 'label' => get_the_title( $ancestor_id ), + 'to' => ccat_is_virtual_page( $ancestor_id ) ? null : str_replace( home_url(), '', get_permalink( $ancestor_id ) ), ); } - $post_type = get_post_type( $post->ID ); - switch ( $post_type ) { - case 'page': - $ancestors = get_post_ancestors( $post->ID ); - if ( ! empty( $ancestors ) ) { - $ancestors = array_reverse( $ancestors ); - foreach ( $ancestors as $ancestor_id ) { - $breadcrumbs[] = array( - 'label' => get_the_title( $ancestor_id ), - 'to' => str_replace( home_url(), '', get_permalink( $ancestor_id ) ), - ); - } - } - break; - - default: - if ( ! empty( $post_id = get_option( "page_for_$post_type" ) ) ) { - // Get ancestors of the archive page - $ancestors = get_post_ancestors( $post_id ); - if ( ! empty( $ancestors ) ) { - $ancestors = array_reverse( $ancestors ); - foreach ( $ancestors as $ancestor_id ) { - $breadcrumbs[] = array( - 'label' => get_the_title( $ancestor_id ), - 'to' => str_replace( home_url(), '', get_permalink( $ancestor_id ) ), - ); - } - } - // Add the archive page itself - $breadcrumbs[] = array( - 'label' => get_the_title( $post_id ), - 'to' => str_replace( home_url(), '', get_permalink( $post_id ) ), - ); - } - break; - } + $breadcrumbs[] = array( + 'label' => get_the_title( $post_id ), + 'to' => null, + ); return $breadcrumbs; } -// Helper: Get breadcrumbs for a given term -function ccat_get_term_breadcrumbs( WP_Term $term ) { - $breadcrumbs = array(); - $taxonomy = $term->taxonomy; - if ( $term->parent ) { - $ancestors = get_ancestors( $term->term_id, $taxonomy ); - if ( ! empty( $ancestors ) ) { - $ancestors = array_reverse( $ancestors ); - foreach ( $ancestors as $ancestor_id ) { - $ancestor_term = get_term( $ancestor_id, $taxonomy ); - if ( $ancestor_term && ! is_wp_error( $ancestor_term ) ) { - $breadcrumbs[] = array( - 'label' => $ancestor_term->name, - 'to' => str_replace( home_url(), '', get_term_link( $ancestor_term ) ), - ); - } - } +// Helper: Get breadcrumbs for a given term ID +function ccat_get_term_breadcrumbs( $term_id ) { + $breadcrumbs = array( + array( + 'label' => 'Accueil', + 'to' => '/', + ), + ); + + $term = get_term( $term_id ); + if ( is_wp_error( $term ) || ! $term ) { + return $breadcrumbs; + } + + $ancestor_ids = get_ancestors( $term->term_id, $term->taxonomy ); + $ancestor_ids = array_reverse( $ancestor_ids ); + foreach ( $ancestor_ids as $ancestor_id ) { + $ancestor_term = get_term( $ancestor_id, $term->taxonomy ); + if ( is_wp_error( $ancestor_term ) || ! $ancestor_term ) { + continue; } + $breadcrumbs[] = array( + 'label' => $ancestor_term->name, + 'to' => str_replace( home_url(), '', get_term_link( $ancestor_term ) ), + ); } + + $breadcrumbs[] = array( + 'label' => $term->name, + 'to' => null, + ); + return $breadcrumbs; } diff --git a/wp-content/themes/ccat/package.json b/wp-content/themes/ccat/package.json index f8afacf..be58362 100644 --- a/wp-content/themes/ccat/package.json +++ b/wp-content/themes/ccat/package.json @@ -39,7 +39,7 @@ "eslint": "^9.36.0", "typescript": "^5.9.2", "vue-tsc": "^3.0.8", - "wrangler": "^4.40.0" + "wrangler": "^4.40.1" }, "packageManager": "pnpm@10.15.0", "pnpm": { diff --git a/wp-content/themes/ccat/pnpm-lock.yaml b/wp-content/themes/ccat/pnpm-lock.yaml index 9ed1d82..38da75b 100644 --- a/wp-content/themes/ccat/pnpm-lock.yaml +++ b/wp-content/themes/ccat/pnpm-lock.yaml @@ -73,8 +73,8 @@ importers: specifier: ^3.0.8 version: 3.0.8(typescript@5.9.2) wrangler: - specifier: ^4.40.0 - version: 4.40.0(@cloudflare/workers-types@4.20250924.0) + specifier: ^4.40.1 + version: 4.40.1(@cloudflare/workers-types@4.20250924.0) packages: @@ -106,8 +106,8 @@ packages: resolution: {integrity: sha512-6o7Y2SeO9vFKB8lArHXehNuusnpddKPk7xqL7T2/b+OvXMRIXUO1rR4wcv1hAFUAT9avGZshty3Wlua/XA7TvA==} engines: {node: '>=18'} - '@ai-sdk/vue@2.0.52': - resolution: {integrity: sha512-r2p+Z0DQNckgIyzUz7CzCJfGoOnwV8Z7HYYb0AuR3+maCqlpKQlovDDp3e171Z2WY+JBWof1UYSnOlcrWIrQig==} + '@ai-sdk/vue@2.0.53': + resolution: {integrity: sha512-IZ0a5oF82tjpfQbjWieTmuzNlovrH5xjunSaHdOcvNCVRSnJiiguHuf/NJXO2999OsfTRFRJO8KAbjogPltp7w==} engines: {node: '>=18'} peerDependencies: vue: ^3.3.4 @@ -1009,8 +1009,8 @@ packages: '@iconify-json/lucide@1.2.68': resolution: {integrity: sha512-lR5xNJdn2CT0iR7lM25G4SewBO4G2hbr3fTWOc3AE9BspflEcneh02E3l9TBaCU/JOHozTJevWLrxBGypD7Tng==} - '@iconify/collections@1.0.597': - resolution: {integrity: sha512-itoqOLcEmgoj+4I92R+PUAnSyhDWN7Ez1QjQvp08ww5EMVeAM5x3Zt3Snf1MS7R5SMM9rl3h7kPRY6+m6g4BwQ==} + '@iconify/collections@1.0.598': + resolution: {integrity: sha512-Mm3gHh0gwgi2T6sYygmCF9A+QirG8E+yCFqLd2zjXNmacbQ4ng0bHTP9QRZqNh96ao4YxxyKAcZyedjW35Wevw==} '@iconify/types@2.0.0': resolution: {integrity: sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==} @@ -2544,8 +2544,8 @@ packages: resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==} engines: {node: '>=8'} - ai@5.0.52: - resolution: {integrity: sha512-GLlRHjMlvN9+w7UYGxCpUQ8GgCRv5Z+JCprRH3Q8YbXJ/JyIc6EP9+YRUmQsyExX/qQsuehe7y/LLygarbSTOw==} + ai@5.0.53: + resolution: {integrity: sha512-TIRelwDRczBS6vGLbJlskC1jLRKUT7DAYz+1DiHjJrgx1MnE2a5xQWv06koLHT+r0GImpkmqP77/n+Vbvea3aw==} engines: {node: '>=18'} peerDependencies: zod: ^3.25.76 || ^4 @@ -3267,8 +3267,8 @@ packages: ee-first@1.1.1: resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} - electron-to-chromium@1.5.223: - resolution: {integrity: sha512-qKm55ic6nbEmagFlTFczML33rF90aU+WtrJ9MdTCThrcvDNdUHN4p6QfVN78U06ZmguqXIyMPyYhw2TrbDUwPQ==} + electron-to-chromium@1.5.224: + resolution: {integrity: sha512-kWAoUu/bwzvnhpdZSIc6KUyvkI1rbRXMT0Eq8pKReyOyaPZcctMli+EgvcN1PAvwVc7Tdo4Fxi2PsLNDU05mdg==} embla-carousel-auto-height@8.6.0: resolution: {integrity: sha512-/HrJQOEM6aol/oF33gd2QlINcXy3e19fJWvHDuHWp2bpyTa+2dm9tVVJak30m2Qy6QyQ6Fc8DkImtv7pxWOJUQ==} @@ -6157,8 +6157,8 @@ packages: engines: {node: '>=16'} hasBin: true - wrangler@4.40.0: - resolution: {integrity: sha512-HCPNUz599h9emi6qjppn92kxS6E12QvD0A3K087CZFEysw6lO1saZUdJ8azk0LsYGYDnrkBs5TzUOEfpuccwWA==} + wrangler@4.40.1: + resolution: {integrity: sha512-XQEHOW6g1zW2xnBq1dmhDbEiVBbPGh7mX1tQAUMqKETa61XXvxHCJSzVI3is5xuo9HzZ8ITzg4VnhB/91cg9DQ==} engines: {node: '>=18.0.0'} hasBin: true peerDependencies: @@ -6304,10 +6304,10 @@ snapshots: dependencies: json-schema: 0.4.0 - '@ai-sdk/vue@2.0.52(vue@3.5.22(typescript@5.9.2))(zod@4.1.11)': + '@ai-sdk/vue@2.0.53(vue@3.5.22(typescript@5.9.2))(zod@4.1.11)': dependencies: '@ai-sdk/provider-utils': 3.0.9(zod@4.1.11) - ai: 5.0.52(zod@4.1.11) + ai: 5.0.53(zod@4.1.11) swrv: 1.1.0(vue@3.5.22(typescript@5.9.2)) optionalDependencies: vue: 3.5.22(typescript@5.9.2) @@ -7354,7 +7354,7 @@ snapshots: dependencies: '@iconify/types': 2.0.0 - '@iconify/collections@1.0.597': + '@iconify/collections@1.0.598': dependencies: '@iconify/types': 2.0.0 @@ -7815,7 +7815,7 @@ snapshots: '@nuxt/icon@2.0.0(magicast@0.3.5)(vite@7.1.7(@types/node@24.5.2)(jiti@2.6.0)(lightningcss@1.30.1)(terser@5.44.0)(yaml@2.8.1))(vue@3.5.22(typescript@5.9.2))': dependencies: - '@iconify/collections': 1.0.597 + '@iconify/collections': 1.0.598 '@iconify/types': 2.0.0 '@iconify/utils': 3.0.2 '@iconify/vue': 5.0.0(vue@3.5.22(typescript@5.9.2)) @@ -7957,7 +7957,7 @@ snapshots: '@nuxt/ui@4.0.0(@babel/parser@7.28.4)(@netlify/blobs@9.1.2)(change-case@5.4.4)(db0@0.3.2)(embla-carousel@8.6.0)(ioredis@5.8.0)(jwt-decode@4.0.0)(magicast@0.3.5)(typescript@5.9.2)(vite@7.1.7(@types/node@24.5.2)(jiti@2.6.0)(lightningcss@1.30.1)(terser@5.44.0)(yaml@2.8.1))(vue-router@4.5.1(vue@3.5.22(typescript@5.9.2)))(vue@3.5.22(typescript@5.9.2))(zod@4.1.11)': dependencies: - '@ai-sdk/vue': 2.0.52(vue@3.5.22(typescript@5.9.2))(zod@4.1.11) + '@ai-sdk/vue': 2.0.53(vue@3.5.22(typescript@5.9.2))(zod@4.1.11) '@iconify/vue': 5.0.0(vue@3.5.22(typescript@5.9.2)) '@internationalized/date': 3.9.0 '@internationalized/number': 3.6.5 @@ -9223,7 +9223,7 @@ snapshots: clean-stack: 2.2.0 indent-string: 4.0.0 - ai@5.0.52(zod@4.1.11): + ai@5.0.53(zod@4.1.11): dependencies: '@ai-sdk/gateway': 1.0.29(zod@4.1.11) '@ai-sdk/provider': 2.0.0 @@ -9407,7 +9407,7 @@ snapshots: dependencies: baseline-browser-mapping: 2.8.7 caniuse-lite: 1.0.30001745 - electron-to-chromium: 1.5.223 + electron-to-chromium: 1.5.224 node-releases: 2.0.21 update-browserslist-db: 1.1.3(browserslist@4.26.2) @@ -9481,7 +9481,7 @@ snapshots: camel-case@4.1.2: dependencies: pascal-case: 3.1.2 - tslib: 2.6.3 + tslib: 2.8.1 caniuse-api@3.0.0: dependencies: @@ -9495,7 +9495,7 @@ snapshots: capital-case@1.0.4: dependencies: no-case: 3.0.4 - tslib: 2.6.3 + tslib: 2.8.1 upper-case-first: 2.0.2 case-anything@3.1.2: {} @@ -9533,7 +9533,7 @@ snapshots: path-case: 3.0.4 sentence-case: 3.0.4 snake-case: 3.0.4 - tslib: 2.6.3 + tslib: 2.8.1 change-case@5.4.4: {} @@ -9658,7 +9658,7 @@ snapshots: constant-case@3.0.4: dependencies: no-case: 3.0.4 - tslib: 2.6.3 + tslib: 2.8.1 upper-case: 2.0.2 convert-source-map@2.0.0: {} @@ -9903,7 +9903,7 @@ snapshots: dot-case@3.0.4: dependencies: no-case: 3.0.4 - tslib: 2.6.3 + tslib: 2.8.1 dot-prop@9.0.0: dependencies: @@ -9928,7 +9928,7 @@ snapshots: ee-first@1.1.1: {} - electron-to-chromium@1.5.223: {} + electron-to-chromium@1.5.224: {} embla-carousel-auto-height@8.6.0(embla-carousel@8.6.0): dependencies: @@ -10648,7 +10648,7 @@ snapshots: header-case@2.0.4: dependencies: capital-case: 1.0.4 - tslib: 2.6.3 + tslib: 2.8.1 hey-listen@1.0.8: {} @@ -10852,7 +10852,7 @@ snapshots: is-lower-case@2.0.2: dependencies: - tslib: 2.6.3 + tslib: 2.8.1 is-module@1.0.0: {} @@ -10884,7 +10884,7 @@ snapshots: is-upper-case@2.0.2: dependencies: - tslib: 2.6.3 + tslib: 2.8.1 is-what@4.1.16: {} @@ -11130,11 +11130,11 @@ snapshots: lower-case-first@2.0.2: dependencies: - tslib: 2.6.3 + tslib: 2.8.1 lower-case@2.0.2: dependencies: - tslib: 2.6.3 + tslib: 2.8.1 lru-cache@10.4.3: {} @@ -11430,7 +11430,7 @@ snapshots: no-case@3.0.4: dependencies: lower-case: 2.0.2 - tslib: 2.6.3 + tslib: 2.8.1 node-abi@3.77.0: dependencies: @@ -11876,7 +11876,7 @@ snapshots: param-case@3.0.4: dependencies: dot-case: 3.0.4 - tslib: 2.6.3 + tslib: 2.8.1 parent-module@1.0.1: dependencies: @@ -11918,14 +11918,14 @@ snapshots: pascal-case@3.1.2: dependencies: no-case: 3.0.4 - tslib: 2.6.3 + tslib: 2.8.1 path-browserify@1.0.1: {} path-case@3.0.4: dependencies: dot-case: 3.0.4 - tslib: 2.6.3 + tslib: 2.8.1 path-exists@4.0.0: {} @@ -12427,7 +12427,7 @@ snapshots: sentence-case@3.0.4: dependencies: no-case: 3.0.4 - tslib: 2.6.3 + tslib: 2.8.1 upper-case-first: 2.0.2 serialize-javascript@6.0.2: @@ -12596,7 +12596,7 @@ snapshots: snake-case@3.0.4: dependencies: dot-case: 3.0.4 - tslib: 2.6.3 + tslib: 2.8.1 source-map-js@1.2.1: {} @@ -12622,7 +12622,7 @@ snapshots: sponge-case@1.0.1: dependencies: - tslib: 2.6.3 + tslib: 2.8.1 stable-hash-x@0.2.0: {} @@ -12741,7 +12741,7 @@ snapshots: swap-case@2.0.2: dependencies: - tslib: 2.6.3 + tslib: 2.8.1 swrv@1.1.0(vue@3.5.22(typescript@5.9.2)): dependencies: @@ -12842,7 +12842,7 @@ snapshots: title-case@3.0.3: dependencies: - tslib: 2.6.3 + tslib: 2.8.1 to-regex-range@5.0.1: dependencies: @@ -13097,11 +13097,11 @@ snapshots: upper-case-first@2.0.2: dependencies: - tslib: 2.6.3 + tslib: 2.8.1 upper-case@2.0.2: dependencies: - tslib: 2.6.3 + tslib: 2.8.1 uqr@0.1.2: {} @@ -13300,7 +13300,7 @@ snapshots: '@cloudflare/workerd-linux-arm64': 1.20250924.0 '@cloudflare/workerd-windows-64': 1.20250924.0 - wrangler@4.40.0(@cloudflare/workers-types@4.20250924.0): + wrangler@4.40.1(@cloudflare/workers-types@4.20250924.0): dependencies: '@cloudflare/kv-asset-handler': 0.4.0 '@cloudflare/unenv-preset': 2.7.4(unenv@2.0.0-rc.21)(workerd@1.20250924.0) diff --git a/wp-content/themes/ccat/server/schema.graphql b/wp-content/themes/ccat/server/schema.graphql index 3f777fd..52a4e95 100644 --- a/wp-content/themes/ccat/server/schema.graphql +++ b/wp-content/themes/ccat/server/schema.graphql @@ -24891,6 +24891,12 @@ type TemplateToTemplateConnectionPageInfo implements PageInfo & TemplateConnecti startCursor: String } +"""The template assigned to the node""" +type Template_VirtualPage implements ContentTemplate { + """The name of the template""" + templateName: String +} + """ Base interface for taxonomy terms such as categories and tags. Terms are used to organize and classify content. """ diff --git a/wp-content/themes/ccat/virtual.php b/wp-content/themes/ccat/virtual.php new file mode 100644 index 0000000..ce2a671 --- /dev/null +++ b/wp-content/themes/ccat/virtual.php @@ -0,0 +1,2 @@ +