Skip to content

Instantly share code, notes, and snippets.

@kaliop-lblois
Last active June 26, 2025 07:11
Show Gist options
  • Select an option

  • Save kaliop-lblois/7bdf1bea5100f777ed9de5a8c69060ad to your computer and use it in GitHub Desktop.

Select an option

Save kaliop-lblois/7bdf1bea5100f777ed9de5a8c69060ad to your computer and use it in GitHub Desktop.
import {
Box,
Button,
Combobox,
ComboboxOption,
Dialog,
DialogBody,
DialogFooter,
SingleSelect,
SingleSelectOption
} from "@strapi/design-system"
import { useEffect, useMemo, useState } from "react"
import pluginId from "../pluginId"
import { useContentSearch } from "../hooks/useContentSearch"
import { useContentTypes } from "../hooks/useContentTypes"
export function ContentModal() {
const [editor, setEditor] = useState<any>()
const visible = useMemo(() => editor !== undefined, [editor])
const closeModal = () => setEditor(undefined)
const contentTypes = useContentTypes()
const { contentType, setContentType, search, setSearch, searchResults, setContentId, contentId } = useContentSearch()
useEffect(() => {
document.addEventListener(pluginId, (event) => {
// @ts-ignore
setEditor(event.detail.editor)
})
}, [])
const onApply = () => {
editor.commands.get(pluginId).execute({
"data-plugin": pluginId,
"data-content-type": contentType,
"data-content-id": contentId,
style: "color: #006096"
})
setEditor(undefined)
}
return (
<Dialog onClose={closeModal} title="Pick your content" isOpen={visible}>
<DialogBody>
<Box>
<Box marginBottom={2}>
<SingleSelect value={contentType} onChange={setContentType} label="Content type" placeholder="Article...">
{contentTypes.map((contentType) => (
<SingleSelectOption value={contentType.uid}>{contentType.info.displayName}</SingleSelectOption>
))}
</SingleSelect>
</Box>
<Box marginBottom={2}>
<Combobox
label="Content title"
disabled={!contentType}
value={search}
onInputChange={(event: any) => {
const value = event.target.value
if (value) {
setSearch(value)
}
}}
onChange={setContentId}
>
{(searchResults.hits || []).map((hit: any) => (
// @ts-ignore
<ComboboxOption value={hit.id}>{hit[searchResults.attribute]}</ComboboxOption>
))}
</Combobox>
</Box>
<Button disabled={!contentType && !contentId} onClick={onApply}>
Apply
</Button>
</Box>
</DialogBody>
<DialogFooter
startAction={
<Button onClick={closeModal} variant="tertiary">
Close
</Button>
}
/>
</Dialog>
)
}
import { Strapi } from "@strapi/strapi"
import { StrapiContentType } from "../../interfaces"
export default ({ strapi }: { strapi: Strapi }) => ({
getContentTypesDefinition() {
return Object.values(strapi.contentTypes).filter((contentType) =>
// @ts-ignore
contentType.uid.startsWith("api::")
) as StrapiContentType[]
},
async searchContent(contentTypeUid: string, search: string, locale: string) {
const contentTypes = this.getContentTypesDefinition() as StrapiContentType[]
const contentType = contentTypes.find((contentType) => contentType.uid === contentTypeUid)
if (!contentType) return { attribute: null, hits: [] }
const searchableAttribute = getSearchableAttribute(contentType)
if (!searchableAttribute) return { attribute: null, hits: [] }
// @ts-ignore
const rawHits = await strapi.entityService.findMany(contentTypeUid, {
filters: {
[searchableAttribute]: {
$containsi: search
}
},
locale
})
// @ts-ignore
const isDraftAndPublish = contentType.pluginOptions.draftAndPublish
const hits = isDraftAndPublish ? rawHits?.filter((hit) => hit.publishDate !== null) : rawHits
return { attribute: searchableAttribute, hits }
},
async getContents(contents: { contentType: string; contentId: string }[]) {
const items: any[] = []
for (const { contentType, contentId } of contents) {
// @ts-ignore
const hit = await strapi.entityService.findOne(contentType, contentId)
items.push({ contentType, contentId, entry: hit })
}
return items
}
})
function getSearchableAttribute(contentType: StrapiContentType): string | undefined {
for (const attribute in contentType.attributes) {
const definition = contentType.attributes[attribute] as any
if (definition.type !== "string") continue
return attribute
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment