feat: search
This commit is contained in:
@@ -3,9 +3,9 @@ import path from 'path'
|
||||
const filename = fileURLToPath(import.meta.url)
|
||||
const dirname = path.dirname(filename)
|
||||
import { buildConfigWithDefaults } from '../buildConfigWithDefaults.js'
|
||||
import { devUser } from '../credentials.js'
|
||||
import { Media } from './collections/Media/index.js'
|
||||
import { Posts } from './collections/Posts/index.js'
|
||||
import { seed } from './seed/index.js'
|
||||
|
||||
export default buildConfigWithDefaults({
|
||||
admin: {
|
||||
@@ -14,94 +14,13 @@ export default buildConfigWithDefaults({
|
||||
},
|
||||
},
|
||||
collections: [Posts, Media],
|
||||
onInit: async (payload) => {
|
||||
await payload.create({
|
||||
collection: 'users',
|
||||
data: {
|
||||
email: devUser.email,
|
||||
password: devUser.password,
|
||||
},
|
||||
})
|
||||
await payload.create({
|
||||
collection: '_folders',
|
||||
data: {
|
||||
name: 'Root',
|
||||
isRoot: true,
|
||||
},
|
||||
})
|
||||
const memesFolder = await payload.create({
|
||||
collection: '_folders',
|
||||
data: {
|
||||
name: 'Memes',
|
||||
},
|
||||
})
|
||||
const nateMemesFolder = await payload.create({
|
||||
collection: '_folders',
|
||||
data: {
|
||||
name: 'Nate Memes',
|
||||
_parentFolder: memesFolder.id,
|
||||
},
|
||||
})
|
||||
await payload.create({
|
||||
collection: '_folders',
|
||||
data: {
|
||||
name: 'Sacred Nate Memes',
|
||||
_parentFolder: nateMemesFolder.id,
|
||||
},
|
||||
})
|
||||
await payload.create({
|
||||
collection: 'posts',
|
||||
data: {
|
||||
title: 'Nate Shambles',
|
||||
_parentFolder: nateMemesFolder.id,
|
||||
},
|
||||
})
|
||||
await payload.create({
|
||||
collection: 'posts',
|
||||
data: {
|
||||
title: 'The Den',
|
||||
_parentFolder: nateMemesFolder.id,
|
||||
},
|
||||
})
|
||||
await payload.create({
|
||||
collection: 'posts',
|
||||
data: {
|
||||
title: 'Marekteer',
|
||||
_parentFolder: nateMemesFolder.id,
|
||||
},
|
||||
})
|
||||
await payload.create({
|
||||
collection: 'posts',
|
||||
data: {
|
||||
title: 'Nate+James',
|
||||
_parentFolder: nateMemesFolder.id,
|
||||
},
|
||||
})
|
||||
await payload.create({
|
||||
collection: '_folders',
|
||||
data: {
|
||||
name: 'Social',
|
||||
},
|
||||
})
|
||||
await payload.create({
|
||||
collection: '_folders',
|
||||
data: {
|
||||
name: 'Slack Emojis',
|
||||
},
|
||||
})
|
||||
await payload.create({
|
||||
collection: '_folders',
|
||||
data: {
|
||||
name: 'This is a really long folder name',
|
||||
},
|
||||
})
|
||||
await payload.create({
|
||||
collection: 'posts',
|
||||
data: {
|
||||
title: 'Post 1',
|
||||
},
|
||||
})
|
||||
},
|
||||
globals: [
|
||||
{
|
||||
slug: 'global',
|
||||
fields: [],
|
||||
},
|
||||
],
|
||||
onInit: seed,
|
||||
typescript: {
|
||||
outputFile: path.resolve(dirname, 'payload-types.ts'),
|
||||
},
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { Payload, Where } from 'payload'
|
||||
import type { Payload } from 'payload'
|
||||
|
||||
import path from 'path'
|
||||
import { fileURLToPath } from 'url'
|
||||
@@ -34,7 +34,7 @@ describe('folders', () => {
|
||||
},
|
||||
})
|
||||
await payload.delete({
|
||||
collection: 'folders',
|
||||
collection: '_folders',
|
||||
depth: 0,
|
||||
where: {
|
||||
id: {
|
||||
@@ -47,21 +47,21 @@ describe('folders', () => {
|
||||
describe('folder > subfolder querying', () => {
|
||||
it('should only create 1 root folder', async () => {
|
||||
await payload.create({
|
||||
collection: 'folders',
|
||||
collection: '_folders',
|
||||
data: {
|
||||
name: 'Folder 1',
|
||||
},
|
||||
})
|
||||
|
||||
await payload.create({
|
||||
collection: 'folders',
|
||||
collection: '_folders',
|
||||
data: {
|
||||
name: 'Folder 2',
|
||||
},
|
||||
})
|
||||
|
||||
const rootSubfoldersQuery = await payload.find({
|
||||
collection: 'folders',
|
||||
collection: '_folders',
|
||||
where: {
|
||||
isRoot: {
|
||||
equals: true,
|
||||
@@ -70,26 +70,26 @@ describe('folders', () => {
|
||||
})
|
||||
|
||||
expect(rootSubfoldersQuery.docs).toHaveLength(1)
|
||||
expect(rootSubfoldersQuery.docs[0].parentFolder).toBe(undefined)
|
||||
expect(rootSubfoldersQuery.docs[0]._parentFolder).toBe(undefined)
|
||||
})
|
||||
|
||||
it('should populate subfolders for root', async () => {
|
||||
await payload.create({
|
||||
collection: 'folders',
|
||||
collection: '_folders',
|
||||
data: {
|
||||
name: 'Folder 1',
|
||||
},
|
||||
})
|
||||
|
||||
await payload.create({
|
||||
collection: 'folders',
|
||||
collection: '_folders',
|
||||
data: {
|
||||
name: 'Folder 2',
|
||||
},
|
||||
})
|
||||
|
||||
const rootSubfoldersQuery = await payload.find({
|
||||
collection: 'folders',
|
||||
collection: '_folders',
|
||||
where: {
|
||||
isRoot: {
|
||||
equals: true,
|
||||
@@ -97,12 +97,12 @@ describe('folders', () => {
|
||||
},
|
||||
})
|
||||
|
||||
expect(rootSubfoldersQuery.docs[0].documentsAndFolders.docs.length).toBe(2)
|
||||
expect(rootSubfoldersQuery.docs[0].documentsAndFolders.docs).toHaveLength(2)
|
||||
})
|
||||
|
||||
it('should populate subfolders for folder by ID', async () => {
|
||||
const parentFolder = await payload.create({
|
||||
collection: 'folders',
|
||||
collection: '_folders',
|
||||
data: {
|
||||
name: 'Parent Folder',
|
||||
},
|
||||
@@ -110,7 +110,7 @@ describe('folders', () => {
|
||||
const folderIDFromParams = parentFolder.id
|
||||
|
||||
await payload.create({
|
||||
collection: 'folders',
|
||||
collection: '_folders',
|
||||
data: {
|
||||
name: 'Nested 1',
|
||||
parentFolder: folderIDFromParams,
|
||||
@@ -118,7 +118,7 @@ describe('folders', () => {
|
||||
})
|
||||
|
||||
await payload.create({
|
||||
collection: 'folders',
|
||||
collection: '_folders',
|
||||
data: {
|
||||
name: 'Nested 2',
|
||||
parentFolder: folderIDFromParams,
|
||||
@@ -126,18 +126,18 @@ describe('folders', () => {
|
||||
})
|
||||
|
||||
const parentFolderQuery = await payload.findByID({
|
||||
collection: 'folders',
|
||||
collection: '_folders',
|
||||
id: folderIDFromParams,
|
||||
})
|
||||
|
||||
expect(parentFolderQuery.documentsAndFolders.docs.length).toBe(2)
|
||||
expect(parentFolderQuery.documentsAndFolders.docs).toHaveLength(2)
|
||||
})
|
||||
})
|
||||
|
||||
describe('folder > file querying', () => {
|
||||
it.skip('should populate files for folder by ID [POLYMORPHIC NOT IMPLEMENTED]', async () => {
|
||||
const parentFolder = await payload.create({
|
||||
collection: 'folders',
|
||||
collection: '_folders',
|
||||
data: {
|
||||
name: 'Parent Folder',
|
||||
},
|
||||
@@ -148,7 +148,7 @@ describe('folders', () => {
|
||||
collection: 'posts',
|
||||
data: {
|
||||
title: 'Post 1',
|
||||
parentFolder: folderIDFromParams,
|
||||
_parentFolder: folderIDFromParams,
|
||||
},
|
||||
})
|
||||
|
||||
@@ -156,21 +156,21 @@ describe('folders', () => {
|
||||
collection: 'posts',
|
||||
data: {
|
||||
title: 'Post 2',
|
||||
parentFolder: folderIDFromParams,
|
||||
_parentFolder: folderIDFromParams,
|
||||
},
|
||||
})
|
||||
|
||||
const parentFolderQuery = await payload.findByID({
|
||||
collection: 'folders',
|
||||
collection: '_folders',
|
||||
id: folderIDFromParams,
|
||||
})
|
||||
|
||||
expect(parentFolderQuery.documentsAndFolders.docs.length).toBe(2)
|
||||
expect(parentFolderQuery.documentsAndFolders.docs).toHaveLength(2)
|
||||
})
|
||||
|
||||
it('should populate files for folder [ISOMORPHIC WORKAROUND]', async () => {
|
||||
const parentFolder = await payload.create({
|
||||
collection: 'folders',
|
||||
collection: '_folders',
|
||||
data: {
|
||||
name: 'Parent Folder',
|
||||
},
|
||||
@@ -181,7 +181,7 @@ describe('folders', () => {
|
||||
collection: 'posts',
|
||||
data: {
|
||||
title: 'Post 1',
|
||||
parentFolder: folderIDFromParams,
|
||||
_parentFolder: folderIDFromParams,
|
||||
},
|
||||
})
|
||||
|
||||
@@ -189,20 +189,20 @@ describe('folders', () => {
|
||||
collection: 'posts',
|
||||
data: {
|
||||
title: 'Post 2',
|
||||
parentFolder: folderIDFromParams,
|
||||
_parentFolder: folderIDFromParams,
|
||||
},
|
||||
})
|
||||
|
||||
const postsByParentQuery = await payload.find({
|
||||
collection: 'posts',
|
||||
where: {
|
||||
parentFolder: {
|
||||
_parentFolder: {
|
||||
equals: folderIDFromParams,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
expect(postsByParentQuery.docs.length).toBe(2)
|
||||
expect(postsByParentQuery.docs).toHaveLength(2)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -6,10 +6,65 @@
|
||||
* and re-run `payload generate:types` to regenerate this file.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Supported timezones in IANA format.
|
||||
*
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "supportedTimezones".
|
||||
*/
|
||||
export type SupportedTimezones =
|
||||
| 'Pacific/Midway'
|
||||
| 'Pacific/Niue'
|
||||
| 'Pacific/Honolulu'
|
||||
| 'Pacific/Rarotonga'
|
||||
| 'America/Anchorage'
|
||||
| 'Pacific/Gambier'
|
||||
| 'America/Los_Angeles'
|
||||
| 'America/Tijuana'
|
||||
| 'America/Denver'
|
||||
| 'America/Phoenix'
|
||||
| 'America/Chicago'
|
||||
| 'America/Guatemala'
|
||||
| 'America/New_York'
|
||||
| 'America/Bogota'
|
||||
| 'America/Caracas'
|
||||
| 'America/Santiago'
|
||||
| 'America/Buenos_Aires'
|
||||
| 'America/Sao_Paulo'
|
||||
| 'Atlantic/South_Georgia'
|
||||
| 'Atlantic/Azores'
|
||||
| 'Atlantic/Cape_Verde'
|
||||
| 'Europe/London'
|
||||
| 'Europe/Berlin'
|
||||
| 'Africa/Lagos'
|
||||
| 'Europe/Athens'
|
||||
| 'Africa/Cairo'
|
||||
| 'Europe/Moscow'
|
||||
| 'Asia/Riyadh'
|
||||
| 'Asia/Dubai'
|
||||
| 'Asia/Baku'
|
||||
| 'Asia/Karachi'
|
||||
| 'Asia/Tashkent'
|
||||
| 'Asia/Calcutta'
|
||||
| 'Asia/Dhaka'
|
||||
| 'Asia/Almaty'
|
||||
| 'Asia/Jakarta'
|
||||
| 'Asia/Bangkok'
|
||||
| 'Asia/Shanghai'
|
||||
| 'Asia/Singapore'
|
||||
| 'Asia/Tokyo'
|
||||
| 'Asia/Seoul'
|
||||
| 'Australia/Sydney'
|
||||
| 'Pacific/Guam'
|
||||
| 'Pacific/Noumea'
|
||||
| 'Pacific/Auckland'
|
||||
| 'Pacific/Fiji';
|
||||
|
||||
export interface Config {
|
||||
auth: {
|
||||
users: UserAuthOperations;
|
||||
};
|
||||
blocks: {};
|
||||
collections: {
|
||||
posts: Post;
|
||||
media: Media;
|
||||
@@ -21,7 +76,7 @@ export interface Config {
|
||||
};
|
||||
collectionsJoins: {
|
||||
_folders: {
|
||||
documentsAndFolders: '_folders';
|
||||
documentsAndFolders: '_folders' | 'posts' | 'media';
|
||||
};
|
||||
};
|
||||
collectionsSelect: {
|
||||
@@ -36,8 +91,12 @@ export interface Config {
|
||||
db: {
|
||||
defaultIDType: string;
|
||||
};
|
||||
globals: {};
|
||||
globalsSelect: {};
|
||||
globals: {
|
||||
global: Global;
|
||||
};
|
||||
globalsSelect: {
|
||||
global: GlobalSelect<false> | GlobalSelect<true>;
|
||||
};
|
||||
locale: null;
|
||||
user: User & {
|
||||
collection: 'users';
|
||||
@@ -74,6 +133,7 @@ export interface Post {
|
||||
title?: string | null;
|
||||
heroImage?: (string | null) | Media;
|
||||
_parentFolder?: (string | null) | FolderInterface;
|
||||
_folderSearch?: string | null;
|
||||
updatedAt: string;
|
||||
createdAt: string;
|
||||
}
|
||||
@@ -83,6 +143,8 @@ export interface Post {
|
||||
*/
|
||||
export interface Media {
|
||||
id: string;
|
||||
_parentFolder?: (string | null) | FolderInterface;
|
||||
_folderSearch?: string | null;
|
||||
updatedAt: string;
|
||||
createdAt: string;
|
||||
url?: string | null;
|
||||
@@ -105,9 +167,25 @@ export interface FolderInterface {
|
||||
_parentFolder?: (string | null) | FolderInterface;
|
||||
isRoot?: boolean | null;
|
||||
documentsAndFolders?: {
|
||||
docs?: (string | FolderInterface)[] | null;
|
||||
docs?:
|
||||
| (
|
||||
| {
|
||||
relationTo?: '_folders';
|
||||
value: string | FolderInterface;
|
||||
}
|
||||
| {
|
||||
relationTo?: 'posts';
|
||||
value: string | Post;
|
||||
}
|
||||
| {
|
||||
relationTo?: 'media';
|
||||
value: string | Media;
|
||||
}
|
||||
)[]
|
||||
| null;
|
||||
hasNextPage?: boolean | null;
|
||||
} | null;
|
||||
_folderSearch?: string | null;
|
||||
updatedAt: string;
|
||||
createdAt: string;
|
||||
}
|
||||
@@ -201,6 +279,7 @@ export interface PostsSelect<T extends boolean = true> {
|
||||
title?: T;
|
||||
heroImage?: T;
|
||||
_parentFolder?: T;
|
||||
_folderSearch?: T;
|
||||
updatedAt?: T;
|
||||
createdAt?: T;
|
||||
}
|
||||
@@ -209,6 +288,8 @@ export interface PostsSelect<T extends boolean = true> {
|
||||
* via the `definition` "media_select".
|
||||
*/
|
||||
export interface MediaSelect<T extends boolean = true> {
|
||||
_parentFolder?: T;
|
||||
_folderSearch?: T;
|
||||
updatedAt?: T;
|
||||
createdAt?: T;
|
||||
url?: T;
|
||||
@@ -245,6 +326,7 @@ export interface _FoldersSelect<T extends boolean = true> {
|
||||
_parentFolder?: T;
|
||||
isRoot?: T;
|
||||
documentsAndFolders?: T;
|
||||
_folderSearch?: T;
|
||||
updatedAt?: T;
|
||||
createdAt?: T;
|
||||
}
|
||||
@@ -280,6 +362,24 @@ export interface PayloadMigrationsSelect<T extends boolean = true> {
|
||||
updatedAt?: T;
|
||||
createdAt?: T;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "global".
|
||||
*/
|
||||
export interface Global {
|
||||
id: string;
|
||||
updatedAt?: string | null;
|
||||
createdAt?: string | null;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "global_select".
|
||||
*/
|
||||
export interface GlobalSelect<T extends boolean = true> {
|
||||
updatedAt?: T;
|
||||
createdAt?: T;
|
||||
globalType?: T;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "auth".
|
||||
|
||||
105
test/folder-view/seed/index.ts
Normal file
105
test/folder-view/seed/index.ts
Normal file
@@ -0,0 +1,105 @@
|
||||
import type { FolderInterface, Post } from 'folder-view/payload-types.js'
|
||||
import type { Config, Payload } from 'payload'
|
||||
|
||||
import { devUser } from '../../credentials.js'
|
||||
|
||||
async function createPost(
|
||||
payload: Payload,
|
||||
{ title, _parentFolder }: Pick<Post, '_parentFolder' | 'title'>,
|
||||
): Promise<Post> {
|
||||
return payload.create({
|
||||
collection: 'posts',
|
||||
data: {
|
||||
title,
|
||||
_parentFolder,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
async function createFolder(
|
||||
payload: Payload,
|
||||
{
|
||||
name,
|
||||
_parentFolder,
|
||||
isRoot = false,
|
||||
}: Pick<FolderInterface, '_parentFolder' | 'isRoot' | 'name'>,
|
||||
): Promise<FolderInterface> {
|
||||
return payload.create({
|
||||
collection: '_folders',
|
||||
data: {
|
||||
name,
|
||||
_parentFolder,
|
||||
isRoot,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
export const seed: Config['onInit'] = async (payload) => {
|
||||
await payload.create({
|
||||
collection: 'users',
|
||||
data: {
|
||||
email: devUser.email,
|
||||
password: devUser.password,
|
||||
},
|
||||
})
|
||||
await createFolder(payload, {
|
||||
name: 'Root',
|
||||
isRoot: true,
|
||||
})
|
||||
const teamFolder = await createFolder(payload, {
|
||||
name: 'Team',
|
||||
})
|
||||
const [designersFolder, engineersFolder, marketingFolder, salesFolder] = await Promise.all(
|
||||
['Designers', 'Engineers', 'Marketing', 'Sales'].map((name) =>
|
||||
createFolder(payload, {
|
||||
name,
|
||||
_parentFolder: teamFolder.id,
|
||||
}),
|
||||
),
|
||||
)
|
||||
|
||||
const marketers = ['Nate']
|
||||
const designers = ['Sarah', 'Tylan']
|
||||
const sales = ['Sean', 'Garrentt', 'Evan']
|
||||
const engineers = [
|
||||
'Jarrod',
|
||||
'James',
|
||||
'Jacob',
|
||||
'Alessio',
|
||||
'Patrik',
|
||||
'Paul',
|
||||
'Dan',
|
||||
'Elliot',
|
||||
'Sasha',
|
||||
'Kendell',
|
||||
'Jessica',
|
||||
'Germán',
|
||||
]
|
||||
|
||||
await Promise.all([
|
||||
...sales.map((title) =>
|
||||
createPost(payload, {
|
||||
title,
|
||||
_parentFolder: salesFolder?.id,
|
||||
}),
|
||||
),
|
||||
...marketers.map((title) =>
|
||||
createPost(payload, {
|
||||
title,
|
||||
_parentFolder: marketingFolder?.id,
|
||||
}),
|
||||
),
|
||||
...engineers.map((title) =>
|
||||
createPost(payload, {
|
||||
title,
|
||||
_parentFolder: engineersFolder?.id,
|
||||
}),
|
||||
),
|
||||
...designers.map((title) =>
|
||||
createPost(payload, {
|
||||
title,
|
||||
_parentFolder: designersFolder?.id,
|
||||
}),
|
||||
),
|
||||
])
|
||||
}
|
||||
Reference in New Issue
Block a user