From 1368261006ee02e31c5de4c367e76fc9ea5deec7 Mon Sep 17 00:00:00 2001 From: Daniel Cousens <413395+dcousens@users.noreply.github.com> Date: Tue, 20 Aug 2024 13:35:34 +1000 Subject: [PATCH] remove authenticatedItem from @keystone-6/core/admin-ui --- .changeset/admin-ui-navigation.md | 5 + .changeset/remove-end-session.md | 5 + docs/content/docs/config/auth.md | 1 + .../docs/guides/custom-admin-ui-navigation.md | 101 +++++-------- .../docs/guides/custom-admin-ui-pages.md | 40 +++--- examples/custom-admin-ui-navigation/README.md | 75 ++++------ .../admin/components/CustomNavigation.tsx | 8 +- .../admin/components/CustomNavigation.tsx | 4 +- examples/custom-session-jwt/schema.graphql | 1 - .../custom-session-next-auth/schema.graphql | 1 - .../custom-session-passport/schema.graphql | 1 - examples/custom-session/schema.graphql | 1 - .../admin/components/CustomNavigation.tsx | 4 +- .../usecase-blog-moderated/schema.graphql | 1 - .../auth/components/Navigation/package.json | 4 + packages/auth/package.json | 6 + packages/auth/src/components/Navigation.tsx | 105 ++++++++++++++ .../auth/src/components/SigninContainer.tsx | 11 +- packages/auth/src/gql/getBaseAuthSchema.ts | 7 + packages/auth/src/index.ts | 10 +- packages/auth/src/pages/InitPage.tsx | 4 +- packages/auth/src/pages/SigninPage.tsx | 36 ++++- packages/auth/src/templates/config.ts | 11 ++ packages/auth/src/templates/init.ts | 21 ++- packages/auth/src/templates/signin.ts | 14 +- .../admin-ui/pages/NoAccessPage/index.tsx | 2 - .../src/admin-ui/components/Navigation.tsx | 77 +++------- .../src/admin-ui/components/SignoutButton.tsx | 40 ------ .../core/src/admin-ui/components/index.ts | 4 +- packages/core/src/admin-ui/context.tsx | 8 +- .../src/admin-ui/system/generateAdminUI.ts | 19 +-- packages/core/src/admin-ui/templates/app.ts | 136 +++++------------- packages/core/src/admin-ui/templates/index.ts | 17 +-- .../src/admin-ui/utils/useLazyMetadata.tsx | 49 +------ .../core/src/lib/core/initialise-lists.ts | 3 +- packages/core/src/lib/createGraphQLSchema.ts | 12 +- packages/core/src/types/admin-meta.ts | 7 - pnpm-lock.yaml | 3 + tests/api-tests/auth.test.ts | 26 +++- tests/api-tests/authed-user.test.ts | 55 ------- 40 files changed, 402 insertions(+), 533 deletions(-) create mode 100644 .changeset/admin-ui-navigation.md create mode 100644 .changeset/remove-end-session.md create mode 100644 packages/auth/components/Navigation/package.json create mode 100644 packages/auth/src/components/Navigation.tsx create mode 100644 packages/auth/src/templates/config.ts delete mode 100644 packages/core/src/admin-ui/components/SignoutButton.tsx delete mode 100644 tests/api-tests/authed-user.test.ts diff --git a/.changeset/admin-ui-navigation.md b/.changeset/admin-ui-navigation.md new file mode 100644 index 00000000000..892ba0d6ce1 --- /dev/null +++ b/.changeset/admin-ui-navigation.md @@ -0,0 +1,5 @@ +--- +"@keystone-6/core": major +--- + +Removes `authenticatedItem` from `@keystone-6/core/admin-ui/components` exports diff --git a/.changeset/remove-end-session.md b/.changeset/remove-end-session.md new file mode 100644 index 00000000000..35482f2e091 --- /dev/null +++ b/.changeset/remove-end-session.md @@ -0,0 +1,5 @@ +--- +"@keystone-6/core": major +--- + +Removes the `EndSession` GraphQL mutation addition when `context.session.end` is defined, extend this yourself if required diff --git a/docs/content/docs/config/auth.md b/docs/content/docs/config/auth.md index ddd01245534..606cb0cdc1c 100644 --- a/docs/content/docs/config/auth.md +++ b/docs/content/docs/config/auth.md @@ -81,6 +81,7 @@ The following elements will be added to the GraphQL API. ```graphql type Mutation { authenticateUserWithPassword(email: String!, password: String!): UserAuthenticationWithPasswordResult! + endSession: Boolean! } type Query { diff --git a/docs/content/docs/guides/custom-admin-ui-navigation.md b/docs/content/docs/guides/custom-admin-ui-navigation.md index 928a4024f18..df51c64ded5 100644 --- a/docs/content/docs/guides/custom-admin-ui-navigation.md +++ b/docs/content/docs/guides/custom-admin-ui-navigation.md @@ -18,8 +18,8 @@ Reference your custom Navigation component in the export as so. ```ts // /admin/config.ts -import type { AdminConfig } from '@keystone-6/core/types'; -import { CustomNavigation } from './components/CustomNavigation'; +import type { AdminConfig } from '@keystone-6/core/types' +import { CustomNavigation } from './components/CustomNavigation' export const components: AdminConfig['components'] = { Navigation: CustomNavigation @@ -36,8 +36,8 @@ Here we'll export our `CustomNavigation` component as a named export. ```tsx // admin/components/CustomNavigation.tsx -import type { NavigationProps } from '@keystone-6/core/admin-ui/components'; -export function CustomNavigation({ authenticatedItem, lists }: NavigationProps) { +import type { NavigationProps } from '@keystone-6/core/admin-ui/components' +export function CustomNavigation({ lists }: NavigationProps) { return ( {/* ... */} ) @@ -48,8 +48,7 @@ Keystone will pass the following props to this component. ```tsx type NavigationProps = { - lists: ListMeta[]; - authenticatedItem: AuthenticatedItem + lists: ListMeta[] } ``` @@ -62,21 +61,20 @@ For more information on the props, please see the [Navigation Props](#navigation Next we'll want to import some components that Keystone provides to help us build our custom Navigation. ```tsx -import { NavigationContainer, NavItem, ListNavItems } from '@keystone-6/core/admin-ui/components'; +import { NavigationContainer, NavItem, ListNavItems } from '@keystone-6/core/admin-ui/components' ``` -The `NavigationContainer` component provides a container around your navigation links, as well as the different states of the `authenticatedItem` prop. We'll need this to: +The `NavigationContainer` component provides a container around your navigation links. - Make our `CustomNavigation` component look and feel like the default Admin UI Navigation component. -- Render out the hamburger menu with additional options should a user session be in progress via the `authenticatedItem` prop. ```tsx -import { NavigationContainer, NavItem, ListNavItems } from '@keystone-6/core/admin-ui/components'; -import type { NavigationProps } from '@keystone-6/core/admin-ui/components'; +import { NavigationContainer, NavItem, ListNavItems } from '@keystone-6/core/admin-ui/components' +import type { NavigationProps } from '@keystone-6/core/admin-ui/components' -export function CustomNavigation({ authenticatedItem, lists }: NavigationProps) { +export function CustomNavigation({ lists }: NavigationProps) { return ( - + {/* ... */} ) @@ -92,12 +90,12 @@ For more information on the `NavigationContainer` see the [NavigationContainer]( The `ListNavItems` component takes the provided Array of `lists` and renders a list of NavItems. We'll use this component to help us easily create NavItems from Keystone lists. ```tsx -import { NavigationContainer, NavItem, ListNavItems } from '@keystone-6/core/admin-ui/components'; -import type { NavigationProps } from '@keystone-6/core/admin-ui/components'; +import { NavigationContainer, NavItem, ListNavItems } from '@keystone-6/core/admin-ui/components' +import type { NavigationProps } from '@keystone-6/core/admin-ui/components' -export function CustomNavigation({ authenticatedItem, lists }: NavigationProps) { +export function CustomNavigation({ lists }: NavigationProps) { return ( - + {/* ... */} @@ -114,12 +112,12 @@ For more information on the `ListNavItems` component, see the [ListNavItems](#li The `NavItem` component is a thin styling and accessibility wrapper around the `Link` component from Next.js. We'll use this component to render our custom route as well as the `Dashboard` route. ```tsx -import { NavigationContainer, NavItem, ListNavItems } from '@keystone-6/core/admin-ui/components'; -import type { NavigationProps } from '@keystone-6/core/admin-ui/components'; +import { NavigationContainer, NavItem, ListNavItems } from '@keystone-6/core/admin-ui/components' +import type { NavigationProps } from '@keystone-6/core/admin-ui/components' -export function CustomNavigation({ authenticatedItem, lists }: NavigationProps) { +export function CustomNavigation({ lists }: NavigationProps) { return ( - + Dashboard @@ -144,12 +142,12 @@ With all that done, your Custom Navigation component should be good to go, and y ```tsx // admin/components/CustomNavigation.tsx -import { NavigationContainer, NavItem, ListNavItems } from '@keystone-6/core/admin-ui/components'; -import type { NavigationProps } from '@keystone-6/core/admin-ui/components'; +import { NavigationContainer, NavItem, ListNavItems } from '@keystone-6/core/admin-ui/components' +import type { NavigationProps } from '@keystone-6/core/admin-ui/components' -export function CustomNavigation({ authenticatedItem, lists }: NavigationProps) { +export function CustomNavigation({ lists }: NavigationProps) { return ( - + Dashboard @@ -161,11 +159,11 @@ export function CustomNavigation({ authenticatedItem, lists }: NavigationProps) // admin/config.ts -import { AdminConfig } from '@keystone-6/core/types'; -import { CustomNavigation } from './components/CustomNavigation'; +import { AdminConfig } from '@keystone-6/core/types' +import { CustomNavigation } from './components/CustomNavigation' export const components: AdminConfig['components'] = { Navigation: CustomNavigation -}; +} ``` Start up your Keystone project, and you should see Custom Navigation with a route to the KeystoneJS docs in the Admin UI. @@ -180,15 +178,14 @@ The rest of this guide will elaborate on some of the details around the helper c This section is to provide more granular information around the props that Keystone passes to your Custom Navigation component. ```tsx -export const CustomNavigation = ({ lists, authenticatedItem }) => {} +export const CustomNavigation = ({ lists }) => {} ``` Keystone passes the following props to your custom Navigation component: ```ts type NavigationProps { - lists: ListMeta[]; - authenticatedItem: AuthenticatedItem; + lists: ListMeta[] } ``` @@ -197,33 +194,17 @@ type NavigationProps { ```typescript type ListMeta = { /** Used for optimising the generated list of NavItems in React */ - key: string; + key: string /** href to the list route in the Admin UI. */ - path: string; + path: string /** Used as the label for each list generated NavItem */ - label: string; + label: string /** Other properties exists, but these are the ones that are relevant to the Navigation implementation */ -}; - -type Lists = ListMeta[]; -``` - -`authenticatedItem` is a union of potential authentication states, expanded on below: +} -```ts -type AuthenticatedItem = - | { state: 'unauthenticated' } - | { state: 'authenticated'; label: string; id: string; listKey: string } - | { state: 'loading' } - | { state: 'error'; error: Error | readonly [GraphQLError, ...GraphQLError[]] }; +type Lists = ListMeta[] ``` -The `authenticatedItem` props is rendered automatically when you pass it into the `NavigationContainer` component. - -{% hint kind="warn" %} -If you render the `authenticatedItem` yourself, make sure you handle all of the possible states. -{% /hint %} - ## Components Keystone exposes a variety of helper components to make building out your custom Admin UI Navigation component easier. These are: @@ -234,24 +215,14 @@ Keystone exposes a variety of helper components to make building out your custom ### NavigationContainer -This component renders containing markup around your navigation links, as well as as the different states of the `authenticatedItem` prop. - -```typescript -type NavigationContainerProps = { - authenticatedItem?: AuthenticatedItem; -} -``` - -{% hint kind="tip" %} -For the shape of the `authenticatedItem` prop, please see the [Navigation Props](#navigation-props) section above. -{% /hint %} +This component renders containing markup around your navigation links. ```tsx import { NavigationContainer} from '@keystone-6/core/admin-ui/components' -export const CustomNavigation = ({ lists, authenticatedItem }) => { +export function CustomNavigation ({ lists }) { return ( - + {/* ... */} ) diff --git a/docs/content/docs/guides/custom-admin-ui-pages.md b/docs/content/docs/guides/custom-admin-ui-pages.md index 1ae24fd08dd..b5ac2d49645 100644 --- a/docs/content/docs/guides/custom-admin-ui-pages.md +++ b/docs/content/docs/guides/custom-admin-ui-pages.md @@ -14,7 +14,7 @@ The default export of every file in this directory is expected to be a valid Rea ```tsx // admin/pages/custom-page.tsx -import Link from 'next/link'; +import Link from 'next/link' export default function CustomPage () { return ( @@ -43,8 +43,8 @@ This `header` prop is rendered out as the page title at the top of the page. ```tsx // admin/pages/custom-page.tsx -import Link from 'next/link'; -import { PageContainer } from '@keystone-6/core/admin-ui/components'; +import Link from 'next/link' +import { PageContainer } from '@keystone-6/core/admin-ui/components' export default function CustomPage () { return ( @@ -66,8 +66,8 @@ Keystone pages leverage the `Heading` component from the `@keystone-ui/core` pac ```tsx // admin/pages/custom-page.tsx. -import { PageContainer } from '@keystone-6/core/admin-ui/components'; -import { Heading } from '@keystone-ui/core'; +import { PageContainer } from '@keystone-6/core/admin-ui/components' +import { Heading } from '@keystone-ui/core' export default function CustomPage () { return ( @@ -91,20 +91,20 @@ First add the following files to the `/admin` directory in the root of your Keys ```tsx // admin/config.ts -import type { AdminConfig } from '@keystone-6/core/types'; -import { CustomNavigation } from './components/CustomNavigation'; +import type { AdminConfig } from '@keystone-6/core/types' +import { CustomNavigation } from './components/CustomNavigation' export const components: AdminConfig['components']= { Navigation: CustomNavigation -}; +} ``` ```tsx // admin/components/CustomNavigation.tsx -import { NavigationContainer, ListNavItems, NavItem } from '@keystone-6/core/admin-ui/components'; -import type { NavigationProps } from '@keystone-6/core/admin-ui/components'; -export function CustomNavigation({ lists, authenticatedItem }: NavigationProps) { +import { NavigationContainer, ListNavItems, NavItem } from '@keystone-6/core/admin-ui/components' +import type { NavigationProps } from '@keystone-6/core/admin-ui/components' +export function CustomNavigation({ lists }: NavigationProps) { return ( - + Dashboard @@ -124,11 +124,11 @@ Lastly we'll add our new route to the newly created `CustomNavigation` component ```tsx // admin/components/CustomNavigation.tsx -import { NavigationContainer, ListNavItems, NavItem } from '@keystone-6/core/admin-ui/components'; -import type { NavigationProps } from '@keystone-6/core/admin-ui/components'; -export function CustomNavigation({ lists, authenticatedItem }: NavigationProps) { +import { NavigationContainer, ListNavItems, NavItem } from '@keystone-6/core/admin-ui/components' +import type { NavigationProps } from '@keystone-6/core/admin-ui/components' +export function CustomNavigation({ lists }: NavigationProps) { return ( - + Dashboard Custom Page @@ -155,10 +155,10 @@ The snippet below uses the emotion `jsx` runtime exported from `@keystone-ui/cor // admin/pages/custom-page.tsx /** @jsxRuntime classic */ -import Link from 'next/link'; -import { jsx } from '@keystone-ui/core'; -import { PageContainer } from '@keystone-6/core/admin-ui/components'; -import { Heading } from '@keystone-ui/core'; +import Link from 'next/link' +import { jsx } from '@keystone-ui/core' +import { PageContainer } from '@keystone-6/core/admin-ui/components' +import { Heading } from '@keystone-ui/core' export default function CustomPage () { return ( diff --git a/examples/custom-admin-ui-navigation/README.md b/examples/custom-admin-ui-navigation/README.md index fa65635f31e..6a60a95e4bd 100644 --- a/examples/custom-admin-ui-navigation/README.md +++ b/examples/custom-admin-ui-navigation/README.md @@ -24,26 +24,26 @@ The project contains an `config.ts` file in the `/admin` directory at its root. export const components = { Logo, Navigation, -}; +} ``` The exported components object is expected to have the following type signature: ```typescript { - Logo?: (props: {}) => ReactElement; - Navigation?: (props: NavigationProps) => ReactElement; + Logo?: (props: {}) => ReactElement + Navigation?: (props: NavigationProps) => ReactElement } ``` Keystone conveniently exports an AdminConfig type for DX. ```typescript -import { AdminConfig } from '@keystone-6/core/types'; +import { AdminConfig } from '@keystone-6/core/types' export const components: AdminConfig['components'] = { Logo, Navigation, -}; +} ``` ## NavigationProps @@ -52,25 +52,10 @@ Keystone passes the following props to your custom Navigation component: ```typescript NavigationProps = { - authenticatedItem: AuthenticatedItem, lists: ListMeta[] } ``` -### authenticatedItem prop - -The authenticatedItem prop is a `Union` representative of the following possible authentication states: - -```typescript -type AuthenticatedItem = - | { state: 'unauthenticated' } - | { state: 'authenticated'; label: string; id: string; listKey: string } - | { state: 'loading' } - | { state: 'error'; error: Error | readonly [GraphQLError, ...GraphQLError[]] }; -``` - -You will need to reasonably account for all of these states if you would like to role your own AuthenticatedItem component but that's out of the scope for this particular example. - ### lists prop The `lists` prop is an array of keystone list objects. @@ -78,56 +63,50 @@ The `lists` prop is an array of keystone list objects. ```typescript type ListMeta = { /** Used for optimising the generated list of NavItems in React */ - key: string; + key: string /** Used as the href for each list generated NavItem */ - path: string; + path: string /** Used as the label for each list generated NavItem */ - label: string; + label: string /** Other properties exists, but these are the ones that are relevant to the Navigation implementation */ -}; +} -type Lists = ListMeta[]; +type Lists = ListMeta[] ``` ## Navigation components Keystone exports the following components to make creating your own custom Navigation component easier. These are: -- NavigationContainer: A generic container element that also includes rendering logic for the passed in authenticatedItem. +- NavigationContainer: A generic container element - ListNavItems: This component renders out a list of Nav Items with preconfigured route matching logic optimised for lists. - NavItem: A thin styling and accessibility wrapper around the Next.js `Link` component. ### NavigationContainer The NavigationContainer is responsible for rendering semantic markup and styles for the containing element around your navigation items. -It's also responsible for rendering out the `authenticatedItem` should it exist. It has the following prop signature: ```typescript type NavigationContainerProps = { - authenticatedItem: AuthenticatedItem; - children: ReactNode; -}; -``` - -Pass it the `authenticatedItem` from the `NavigationProps` for it to handle rendering logic around user signin. + children: ReactNode +} -```tsx -const CustomNavigation = ({ authenticatedItem }) => { +const CustomNavigation = () => { return ( - - {/* The rest of your Nav goes here */} + + {/* the rest goes here */} - ); -}; + ) +} ``` ### ListNavItems ```ts type ListNavItemsProps = { - lists: ListMeta[]; - include?: string[]; -}; + lists: ListMeta[] + include?: string[] +} ``` The ListNavItems component expects `lists` an array of list objects and renders a list of NavItems. It also optionally takes `include`, an array of strings. If this array is passed to this component, only lists with a `key` property that matches an element in the `include` array will be rendered. If this array is not passed into the component, all lists will be rendered. @@ -136,8 +115,8 @@ The ListNavItems component expects `lists` an array of list objects and renders ```typescript type ListNavItemProps = { - list: ListMeta; -}; + list: ListMeta +} ``` The ListNavItem component takes a single `list` object and renders a `NavItem`. This is a thin wrapper around `NavItem`, that automates the association of list properties to NavItem. It also adds a custom `isSelected` expression optimised for keystone lists. @@ -151,10 +130,10 @@ The NavItem component has the following type signature: ```typescript type NavItemProps = { - children: ReactNode; - href: string; - isSelected?: boolean; -}; + children: ReactNode + href: string + isSelected?: boolean +} ``` By default the `isSelected` value if left undefined, will be evaluated by the condition `router.pathname === href`, pass in `isSelected` if you have a custom condition or would like more granular control over the selected state of Navigation items. diff --git a/examples/custom-admin-ui-navigation/admin/components/CustomNavigation.tsx b/examples/custom-admin-ui-navigation/admin/components/CustomNavigation.tsx index 075557fee52..429ded8ebad 100644 --- a/examples/custom-admin-ui-navigation/admin/components/CustomNavigation.tsx +++ b/examples/custom-admin-ui-navigation/admin/components/CustomNavigation.tsx @@ -4,12 +4,12 @@ import { ListNavItems, NavigationContainer, NavItem } from '@keystone-6/core/adm import type { NavigationProps } from '@keystone-6/core/admin-ui/components' -export function CustomNavigation ({ lists, authenticatedItem }: NavigationProps) { +export function CustomNavigation ({ lists }: NavigationProps) { return ( - - Dashboard + + Dashboard - Keystone Docs + Keystone Docs ) } diff --git a/examples/custom-admin-ui-pages/admin/components/CustomNavigation.tsx b/examples/custom-admin-ui-pages/admin/components/CustomNavigation.tsx index 24d18a89ab7..2d4580d7119 100644 --- a/examples/custom-admin-ui-pages/admin/components/CustomNavigation.tsx +++ b/examples/custom-admin-ui-pages/admin/components/CustomNavigation.tsx @@ -2,9 +2,9 @@ import React from 'react' import { NavItem, ListNavItems, NavigationContainer } from '@keystone-6/core/admin-ui/components' import type { NavigationProps } from '@keystone-6/core/admin-ui/components' -export function CustomNavigation ({ lists, authenticatedItem }: NavigationProps) { +export function CustomNavigation ({ lists }: NavigationProps) { return ( - + Dashboard Custom Page diff --git a/examples/custom-session-jwt/schema.graphql b/examples/custom-session-jwt/schema.graphql index 7e53ac4ec31..d5307c28c65 100644 --- a/examples/custom-session-jwt/schema.graphql +++ b/examples/custom-session-jwt/schema.graphql @@ -148,7 +148,6 @@ type Mutation { updateUsers(data: [UserUpdateArgs!]!): [User] deleteUser(where: UserWhereUniqueInput!): User deleteUsers(where: [UserWhereUniqueInput!]!): [User] - endSession: Boolean! } type Query { diff --git a/examples/custom-session-next-auth/schema.graphql b/examples/custom-session-next-auth/schema.graphql index 973b52316fe..56c7eb3febd 100644 --- a/examples/custom-session-next-auth/schema.graphql +++ b/examples/custom-session-next-auth/schema.graphql @@ -182,7 +182,6 @@ type Mutation { updateAuthors(data: [AuthorUpdateArgs!]!): [Author] deleteAuthor(where: AuthorWhereUniqueInput!): Author deleteAuthors(where: [AuthorWhereUniqueInput!]!): [Author] - endSession: Boolean! } type Query { diff --git a/examples/custom-session-passport/schema.graphql b/examples/custom-session-passport/schema.graphql index 973b52316fe..56c7eb3febd 100644 --- a/examples/custom-session-passport/schema.graphql +++ b/examples/custom-session-passport/schema.graphql @@ -182,7 +182,6 @@ type Mutation { updateAuthors(data: [AuthorUpdateArgs!]!): [Author] deleteAuthor(where: AuthorWhereUniqueInput!): Author deleteAuthors(where: [AuthorWhereUniqueInput!]!): [Author] - endSession: Boolean! } type Query { diff --git a/examples/custom-session/schema.graphql b/examples/custom-session/schema.graphql index 7e53ac4ec31..d5307c28c65 100644 --- a/examples/custom-session/schema.graphql +++ b/examples/custom-session/schema.graphql @@ -148,7 +148,6 @@ type Mutation { updateUsers(data: [UserUpdateArgs!]!): [User] deleteUser(where: UserWhereUniqueInput!): User deleteUsers(where: [UserWhereUniqueInput!]!): [User] - endSession: Boolean! } type Query { diff --git a/examples/extend-graphql-subscriptions/admin/components/CustomNavigation.tsx b/examples/extend-graphql-subscriptions/admin/components/CustomNavigation.tsx index 937432d09d1..2b793b86fbf 100644 --- a/examples/extend-graphql-subscriptions/admin/components/CustomNavigation.tsx +++ b/examples/extend-graphql-subscriptions/admin/components/CustomNavigation.tsx @@ -4,9 +4,9 @@ import { ListNavItems, NavigationContainer, NavItem } from '@keystone-6/core/adm import type { NavigationProps } from '@keystone-6/core/admin-ui/components' -export function CustomNavigation ({ lists, authenticatedItem }: NavigationProps) { +export function CustomNavigation ({ lists }: NavigationProps) { return ( - + Dashboard Subscriptions Page diff --git a/examples/usecase-blog-moderated/schema.graphql b/examples/usecase-blog-moderated/schema.graphql index 35c85582bf7..7f6ad2ab001 100644 --- a/examples/usecase-blog-moderated/schema.graphql +++ b/examples/usecase-blog-moderated/schema.graphql @@ -324,7 +324,6 @@ type Mutation { updateUsers(data: [UserUpdateArgs!]!): [User] deleteUser(where: UserWhereUniqueInput!): User deleteUsers(where: [UserWhereUniqueInput!]!): [User] - endSession: Boolean! } type Query { diff --git a/packages/auth/components/Navigation/package.json b/packages/auth/components/Navigation/package.json new file mode 100644 index 00000000000..7d28b00c53f --- /dev/null +++ b/packages/auth/components/Navigation/package.json @@ -0,0 +1,4 @@ +{ + "main": "dist/keystone-6-auth-components-Navigation.cjs.js", + "module": "dist/keystone-6-auth-components-Navigation.esm.js" +} diff --git a/packages/auth/package.json b/packages/auth/package.json index 8c271b817c7..13c651f6498 100644 --- a/packages/auth/package.json +++ b/packages/auth/package.json @@ -17,10 +17,15 @@ "module": "./pages/SigninPage/dist/keystone-6-auth-pages-SigninPage.esm.js", "default": "./pages/SigninPage/dist/keystone-6-auth-pages-SigninPage.cjs.js" }, + "./components/Navigation": { + "module": "./components/Navigation/dist/keystone-6-auth-components-Navigation.esm.js", + "default": "./components/Navigation/dist/keystone-6-auth-components-Navigation.cjs.js" + }, "./package.json": "./package.json" }, "dependencies": { "@babel/runtime": "^7.24.7", + "@keystar/ui": "^0.7.6", "@keystone-ui/button": "workspace:^", "@keystone-ui/core": "workspace:^", "@keystone-ui/fields": "workspace:^", @@ -41,6 +46,7 @@ "preconstruct": { "entrypoints": [ "index.ts", + "components/Navigation.tsx", "pages/*.tsx" ] }, diff --git a/packages/auth/src/components/Navigation.tsx b/packages/auth/src/components/Navigation.tsx new file mode 100644 index 00000000000..e292cf76ea1 --- /dev/null +++ b/packages/auth/src/components/Navigation.tsx @@ -0,0 +1,105 @@ +import React, { useEffect } from 'react' + +import { + type ActionButtonProps, + ActionButton, +} from '@keystar/ui/button' +import { TooltipTrigger, Tooltip } from '@keystar/ui/tooltip' +import { HStack } from '@keystar/ui/layout' +import { Text } from '@keystar/ui/typography' + +import { + useQuery, + useMutation, + gql, +} from '@keystone-6/core/admin-ui/apollo' +import { + DeveloperResources, + ListNavItems, + NavigationContainer, + NavItem +} from '@keystone-6/core/admin-ui/components' +import type { NavigationProps } from '@keystone-6/core/admin-ui/components' + +type AuthenticatedItem = { + label: string + id: string + listKey: string +} + +function AuthItem ({ item }: { item: AuthenticatedItem | null }) { + if (!item) return null + + return ( + + + + Signed in as {item.label} + + + ) +} + +function Footer ({ authItem }: { authItem: AuthenticatedItem | null }) { + return ( + + + + + ) +} + +export default function Navigation ({ lists }: NavigationProps) { + const { data } = useQuery<{ + authenticatedItem: AuthenticatedItem | null + }>(gql` + query whoami { + authenticatedItem { + label + id + listKey + } + } + `) + + return ( + + Dashboard + +