diff --git a/packages/plugin-multi-tenant/src/utilities/addFilterOptionsToFields.ts b/packages/plugin-multi-tenant/src/utilities/addFilterOptionsToFields.ts index 11dc282eaf0..8f977c405ad 100644 --- a/packages/plugin-multi-tenant/src/utilities/addFilterOptionsToFields.ts +++ b/packages/plugin-multi-tenant/src/utilities/addFilterOptionsToFields.ts @@ -1,4 +1,4 @@ -import type { Field, FilterOptionsProps, RelationshipField, Where } from 'payload' +import type { Field, FilterOptionsProps, RelationshipField } from 'payload' import { getTenantFromCookie } from './getTenantFromCookie.js' @@ -7,6 +7,7 @@ type AddFilterOptionsToFieldsArgs = { tenantEnabledCollectionSlugs: string[] tenantEnabledGlobalSlugs: string[] } + export function addFilterOptionsToFields({ fields, tenantEnabledCollectionSlugs, diff --git a/test/plugin-multi-tenant/collections/Links.ts b/test/plugin-multi-tenant/collections/Links.ts deleted file mode 100644 index 23502bd2f74..00000000000 --- a/test/plugin-multi-tenant/collections/Links.ts +++ /dev/null @@ -1,18 +0,0 @@ -import type { CollectionConfig } from 'payload' - -export const LinksCollection: CollectionConfig = { - slug: 'links', - admin: { - useAsTitle: 'title', - }, - fields: [ - { - name: 'title', - type: 'text', - }, - { - name: 'url', - type: 'text', - }, - ], -} diff --git a/test/plugin-multi-tenant/collections/Menu.ts b/test/plugin-multi-tenant/collections/Menu.ts new file mode 100644 index 00000000000..265731a56de --- /dev/null +++ b/test/plugin-multi-tenant/collections/Menu.ts @@ -0,0 +1,43 @@ +import type { CollectionConfig } from 'payload' + +import { menuSlug } from '../shared.js' + +export const Menu: CollectionConfig = { + slug: menuSlug, + admin: { + useAsTitle: 'title', + }, + fields: [ + { + name: 'title', + label: 'Title', + type: 'text', + required: true, + }, + { + name: 'description', + type: 'textarea', + }, + { + name: 'menuItems', + label: 'Menu Items', + type: 'array', + fields: [ + { + name: 'menuItem', + label: 'Menu Item', + type: 'relationship', + relationTo: 'menu-items', + required: true, + admin: { + description: 'Automatically filtered by selected tenant', + }, + }, + { + name: 'active', + type: 'checkbox', + }, + ], + }, + ], +} diff --git a/test/plugin-multi-tenant/collections/MenuItems.ts b/test/plugin-multi-tenant/collections/MenuItems.ts new file mode 100644 index 00000000000..cd863324228 --- /dev/null +++ b/test/plugin-multi-tenant/collections/MenuItems.ts @@ -0,0 +1,17 @@ +import type { CollectionConfig } from 'payload' + +import { menuItemsSlug } from '../shared.js' + +export const MenuItems: CollectionConfig = { + slug: menuItemsSlug, + admin: { + useAsTitle: 'name', + }, + fields: [ + { + name: 'name', + type: 'text', + required: true, + }, + ], +} diff --git a/test/plugin-multi-tenant/collections/Posts.ts b/test/plugin-multi-tenant/collections/Posts.ts deleted file mode 100644 index 9fcf7e65be2..00000000000 --- a/test/plugin-multi-tenant/collections/Posts.ts +++ /dev/null @@ -1,34 +0,0 @@ -import type { CollectionConfig } from 'payload' - -import { postsSlug } from '../shared.js' -import { userFilterOptions } from './Users/filterOptions.js' - -export const Posts: CollectionConfig = { - slug: postsSlug, - labels: { - singular: 'Post', - plural: 'Posts', - }, - admin: { - useAsTitle: 'title', - }, - fields: [ - { - name: 'title', - label: 'Title', - type: 'text', - required: true, - }, - { - name: 'relatedLinks', - relationTo: 'links', - type: 'relationship', - }, - { - name: 'author', - relationTo: 'users', - type: 'relationship', - filterOptions: userFilterOptions, - }, - ], -} diff --git a/test/plugin-multi-tenant/collections/Tenants.ts b/test/plugin-multi-tenant/collections/Tenants.ts index 18730c255f6..9ee324a0ed3 100644 --- a/test/plugin-multi-tenant/collections/Tenants.ts +++ b/test/plugin-multi-tenant/collections/Tenants.ts @@ -19,14 +19,15 @@ export const Tenants: CollectionConfig = { required: true, }, { - name: 'slug', + name: 'domain', type: 'text', required: true, }, { - name: 'domain', - type: 'text', - required: true, + type: 'join', + name: 'users', + collection: 'users', + on: 'tenants.tenant', }, ], } diff --git a/test/plugin-multi-tenant/collections/Users.ts b/test/plugin-multi-tenant/collections/Users.ts deleted file mode 100644 index ebb6b95407d..00000000000 --- a/test/plugin-multi-tenant/collections/Users.ts +++ /dev/null @@ -1,34 +0,0 @@ -import type { CollectionConfig } from 'payload' - -import { usersSlug } from '../shared.js' - -export const Users: CollectionConfig = { - slug: usersSlug, - auth: true, - admin: { - useAsTitle: 'email', - }, - access: { - read: () => true, - }, - fields: [ - // Email added by default - // Add more fields as needed - { - type: 'select', - name: 'roles', - hasMany: true, - options: [ - { - label: 'Admin', - value: 'admin', - }, - { - label: 'User', - value: 'user', - }, - ], - saveToJWT: true, - }, - ], -} diff --git a/test/plugin-multi-tenant/collections/Users/filterOptions.ts b/test/plugin-multi-tenant/collections/Users/filterOptions.ts index 17b389ab45f..8e43b6ebfc5 100644 --- a/test/plugin-multi-tenant/collections/Users/filterOptions.ts +++ b/test/plugin-multi-tenant/collections/Users/filterOptions.ts @@ -1,4 +1,4 @@ -import type { FilterOptions, Where } from 'payload' +import type { FilterOptions } from 'payload' import { getTenantFromCookie } from '@payloadcms/plugin-multi-tenant/utilities' @@ -9,17 +9,8 @@ export const userFilterOptions: FilterOptions = ({ req }) => { } return { - or: [ - { - 'tenants.tenant': { - equals: selectedTenant, - }, - }, - { - roles: { - in: ['admin'], - }, - }, - ], - } as Where + 'tenants.tenant': { + equals: selectedTenant, + }, + } } diff --git a/test/plugin-multi-tenant/components/Icon/styles.css b/test/plugin-multi-tenant/components/Icon/styles.css index 932750a814a..bae463f6d86 100644 --- a/test/plugin-multi-tenant/components/Icon/styles.css +++ b/test/plugin-multi-tenant/components/Icon/styles.css @@ -2,6 +2,7 @@ border-radius: 100%; height: 18px; width: 18px; + background-color: var(--theme-error-300); } [data-selected-tenant-title="Blue Dog"] #tenant-icon { diff --git a/test/plugin-multi-tenant/components/Logo/styles.css b/test/plugin-multi-tenant/components/Logo/styles.css index d329dec3f15..b221ca35316 100644 --- a/test/plugin-multi-tenant/components/Logo/styles.css +++ b/test/plugin-multi-tenant/components/Logo/styles.css @@ -2,6 +2,7 @@ border-radius: 100%; height: 18px; width: 18px; + background-color: var(--theme-error-300); } [data-selected-tenant-title="Blue Dog"] #tenant-logo { diff --git a/test/plugin-multi-tenant/config.ts b/test/plugin-multi-tenant/config.ts index 8b1fe72df9c..c6f877d28c5 100644 --- a/test/plugin-multi-tenant/config.ts +++ b/test/plugin-multi-tenant/config.ts @@ -7,15 +7,14 @@ const dirname = path.dirname(filename) import type { Config as ConfigType } from './payload-types.js' import { buildConfigWithDefaults } from '../buildConfigWithDefaults.js' -import { LinksCollection } from './collections/Links.js' -import { Posts } from './collections/Posts.js' +import { Menu } from './collections/Menu.js' +import { MenuItems } from './collections/MenuItems.js' import { Tenants } from './collections/Tenants.js' -import { Users } from './collections/Users.js' -import { NavigationGlobalCollection } from './globals/Navigation.js' +import { Users } from './collections/Users/index.js' import { seed } from './seed/index.js' export default buildConfigWithDefaults({ - collections: [Users, Tenants, Posts, LinksCollection, NavigationGlobalCollection], + collections: [Tenants, Users, Menu, MenuItems], admin: { importMap: { baseDir: path.resolve(dirname), @@ -47,9 +46,8 @@ export default buildConfigWithDefaults({ access: {}, }, collections: { - posts: {}, - links: {}, - 'navigation-global': { + 'menu-items': {}, + menu: { isGlobal: true, }, }, diff --git a/test/plugin-multi-tenant/globals/Navigation.ts b/test/plugin-multi-tenant/globals/Navigation.ts deleted file mode 100644 index 6ddec67701e..00000000000 --- a/test/plugin-multi-tenant/globals/Navigation.ts +++ /dev/null @@ -1,14 +0,0 @@ -import type { CollectionConfig } from 'payload' - -export const NavigationGlobalCollection: CollectionConfig = { - slug: 'navigation-global', - admin: { - useAsTitle: 'title', - }, - fields: [ - { - name: 'title', - type: 'text', - }, - ], -} diff --git a/test/plugin-multi-tenant/payload-types.ts b/test/plugin-multi-tenant/payload-types.ts index c18d44f2b51..0f46143534c 100644 --- a/test/plugin-multi-tenant/payload-types.ts +++ b/test/plugin-multi-tenant/payload-types.ts @@ -11,22 +11,24 @@ export interface Config { users: UserAuthOperations; }; collections: { - users: User; tenants: Tenant; - posts: Post; - links: Link; - 'navigation-global': NavigationGlobal; + users: User; + menu: Menu; + 'menu-items': MenuItem; 'payload-locked-documents': PayloadLockedDocument; 'payload-preferences': PayloadPreference; 'payload-migrations': PayloadMigration; }; - collectionsJoins: {}; + collectionsJoins: { + tenants: { + users: 'users'; + }; + }; collectionsSelect: { - users: UsersSelect | UsersSelect; tenants: TenantsSelect | TenantsSelect; - posts: PostsSelect | PostsSelect; - links: LinksSelect | LinksSelect; - 'navigation-global': NavigationGlobalSelect | NavigationGlobalSelect; + users: UsersSelect | UsersSelect; + menu: MenuSelect | MenuSelect; + 'menu-items': MenuItemsSelect | MenuItemsSelect; 'payload-locked-documents': PayloadLockedDocumentsSelect | PayloadLockedDocumentsSelect; 'payload-preferences': PayloadPreferencesSelect | PayloadPreferencesSelect; 'payload-migrations': PayloadMigrationsSelect | PayloadMigrationsSelect; @@ -63,6 +65,21 @@ export interface UserAuthOperations { password: string; }; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "tenants". + */ +export interface Tenant { + id: string; + name: string; + domain: string; + users?: { + docs?: (string | User)[] | null; + hasNextPage?: boolean | null; + } | null; + updatedAt: string; + createdAt: string; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "users". @@ -90,49 +107,34 @@ export interface User { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "tenants". + * via the `definition` "menu". */ -export interface Tenant { - id: string; - name: string; - slug: string; - domain: string; - updatedAt: string; - createdAt: string; -} -/** - * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "posts". - */ -export interface Post { +export interface Menu { id: string; tenant?: (string | null) | Tenant; title: string; - relatedLinks?: (string | null) | Link; - author?: (string | null) | User; - updatedAt: string; - createdAt: string; -} -/** - * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "links". - */ -export interface Link { - id: string; - tenant?: (string | null) | Tenant; - title?: string | null; - url?: string | null; + description?: string | null; + menuItems?: + | { + /** + * Automatically filtered by selected tenant + */ + menuItem: string | MenuItem; + active?: boolean | null; + id?: string | null; + }[] + | null; updatedAt: string; createdAt: string; } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "navigation-global". + * via the `definition` "menu-items". */ -export interface NavigationGlobal { +export interface MenuItem { id: string; tenant?: (string | null) | Tenant; - title?: string | null; + name: string; updatedAt: string; createdAt: string; } @@ -143,25 +145,21 @@ export interface NavigationGlobal { export interface PayloadLockedDocument { id: string; document?: - | ({ - relationTo: 'users'; - value: string | User; - } | null) | ({ relationTo: 'tenants'; value: string | Tenant; } | null) | ({ - relationTo: 'posts'; - value: string | Post; + relationTo: 'users'; + value: string | User; } | null) | ({ - relationTo: 'links'; - value: string | Link; + relationTo: 'menu'; + value: string | Menu; } | null) | ({ - relationTo: 'navigation-global'; - value: string | NavigationGlobal; + relationTo: 'menu-items'; + value: string | MenuItem; } | null); globalSlug?: string | null; user: { @@ -205,6 +203,17 @@ export interface PayloadMigration { updatedAt: string; createdAt: string; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "tenants_select". + */ +export interface TenantsSelect { + name?: T; + domain?: T; + users?: T; + updatedAt?: T; + createdAt?: T; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "users_select". @@ -230,45 +239,29 @@ export interface UsersSelect { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "tenants_select". - */ -export interface TenantsSelect { - name?: T; - slug?: T; - domain?: T; - updatedAt?: T; - createdAt?: T; -} -/** - * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "posts_select". - */ -export interface PostsSelect { - tenant?: T; - title?: T; - relatedLinks?: T; - author?: T; - updatedAt?: T; - createdAt?: T; -} -/** - * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "links_select". + * via the `definition` "menu_select". */ -export interface LinksSelect { +export interface MenuSelect { tenant?: T; title?: T; - url?: T; + description?: T; + menuItems?: + | T + | { + menuItem?: T; + active?: T; + id?: T; + }; updatedAt?: T; createdAt?: T; } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "navigation-global_select". + * via the `definition` "menu-items_select". */ -export interface NavigationGlobalSelect { +export interface MenuItemsSelect { tenant?: T; - title?: T; + name?: T; updatedAt?: T; createdAt?: T; } @@ -316,4 +309,4 @@ export interface Auth { declare module 'payload' { // @ts-ignore export interface GeneratedTypes extends Config {} -} \ No newline at end of file +} diff --git a/test/plugin-multi-tenant/seed/index.ts b/test/plugin-multi-tenant/seed/index.ts index 0445c133278..2ae21ec1682 100644 --- a/test/plugin-multi-tenant/seed/index.ts +++ b/test/plugin-multi-tenant/seed/index.ts @@ -1,39 +1,67 @@ import type { Config } from 'payload' -import { devUser, regularUser } from '../../credentials.js' +import { devUser } from '../../credentials.js' export const seed: Config['onInit'] = async (payload) => { // create tenants - const tenant1 = await payload.create({ + const blueDogTenant = await payload.create({ collection: 'tenants', data: { name: 'Blue Dog', - slug: 'blue-dog', domain: 'bluedog.com', }, }) - const tenant2 = await payload.create({ + const steelCatTenant = await payload.create({ collection: 'tenants', data: { name: 'Steel Cat', - slug: 'steel-cat', domain: 'steelcat.com', }, }) - // create posts + // Create blue dog menu items await payload.create({ - collection: 'posts', + collection: 'menu-items', data: { - title: 'Blue Dog Post', - tenant: tenant1.id, + name: 'Chorizo Con Queso and Chips', + tenant: blueDogTenant.id, }, }) await payload.create({ - collection: 'posts', + collection: 'menu-items', data: { - title: 'Steel Cat Post', - tenant: tenant2.id, + name: 'Garlic Parmesan Tots', + tenant: blueDogTenant.id, + }, + }) + await payload.create({ + collection: 'menu-items', + data: { + name: 'Spicy Mac', + tenant: blueDogTenant.id, + }, + }) + + // Create steel cat menu items + await payload.create({ + collection: 'menu-items', + data: { + name: 'Pretzel Bites', + tenant: steelCatTenant.id, + }, + }) + await payload.create({ + collection: 'menu-items', + data: { + name: 'Buffalo Chicken Dip', + tenant: steelCatTenant.id, + }, + }) + await payload.create({ + collection: 'menu-items', + data: { + name: 'Pulled Pork Nachos', + tenant: steelCatTenant.id, }, }) @@ -50,12 +78,44 @@ export const seed: Config['onInit'] = async (payload) => { await payload.create({ collection: 'users', data: { - email: regularUser.email, - password: regularUser.password, + email: 'jane@blue-dog.com', + password: 'test', + roles: ['user'], + tenants: [ + { + tenant: blueDogTenant.id, + }, + ], + }, + }) + + // create menus + await payload.create({ + collection: 'menu', + data: { + description: 'This collection behaves like globals, 1 document per tenant. No list view.', + title: 'Blue Dog Menu', + tenant: blueDogTenant.id, + }, + }) + await payload.create({ + collection: 'menu', + data: { + description: 'This collection behaves like globals, 1 document per tenant. No list view.', + title: 'Steel Cat Menu', + tenant: steelCatTenant.id, + }, + }) + + await payload.create({ + collection: 'users', + data: { + email: 'huel@steel-cat.com', + password: 'test', roles: ['user'], tenants: [ { - tenant: tenant1.id, + tenant: steelCatTenant.id, }, ], }, diff --git a/test/plugin-multi-tenant/shared.ts b/test/plugin-multi-tenant/shared.ts index 35466718bf1..1567d175c0a 100644 --- a/test/plugin-multi-tenant/shared.ts +++ b/test/plugin-multi-tenant/shared.ts @@ -1,5 +1,7 @@ export const tenantsSlug = 'tenants' -export const postsSlug = 'posts' - export const usersSlug = 'users' + +export const menuItemsSlug = 'menu-items' + +export const menuSlug = 'menu'