sanity-algolia get error when using pt::text - next.js

I'm trying to integrate algolia search with sanity CMS using the sanity-algolia library (ref https://www.sanity.io/plugins/sanity-algolia)
But when i try to get the plain text from Portable Text rich text content using the pt::text function.
i get expected '}' following object body , and i dont really know where im missing a bracket.
(another note: since im hosting sanity by using sanity start, I am using nextjs (my frontend) to run the function instead using the /api routes in nextJS) So sanity has a webhook to this route.
details about the error:
details: {
description: "expected '}' following object body",
end: 174,
query: '* [(_id in $created || _id in $updated) && _type in $types] {\n' +
' _id,\n' +
' _type,\n' +
' _rev,\n' +
' _type == "post" => {\n' +
' title,\n' +
' "path": slug.current,\n' +
' "body": pt::text(body)\n' +
' }\n' +
'}',
start: 107,
type: 'queryParseError'
}
this is the serverless function im running:
export default async function handler(req, res) {
if (req.headers["content-type"] !== "application/json") {
res.status(400);
res.json({ message: "Bad request" });
return;
}
const algoliaIndex = algolia.initIndex("dev_kim_miles");
const sanityAlgolia = indexer(
{
post: {
index: algoliaIndex,
projection: `{
title,
"path": slug.current,
"body": pt::text(body)
}`,
},
},
(document) => {
console.log(document);
return document;
},
(document) => {
if (document.hasOwnProperty("isHidden")) {
return !document.isHidden;
}
return true;
}
);
return sanityAlgolia
.webhookSync(sanityClient, req.body)
.then(() => res.status(200).send("ok"));
}
and my post schema from sanity:
export default {
name: 'post',
title: 'Post',
type: 'document',
fields: [
{
name: 'title',
title: 'Title',
type: 'string',
},
{
name: 'slug',
title: 'Slug',
type: 'slug',
options: {
source: 'title',
maxLength: 96,
},
},
{
name: 'author',
title: 'Author',
type: 'reference',
to: {type: 'author'},
},
{
name: 'mainImage',
title: 'Main image',
type: 'image',
options: {
hotspot: true,
},
},
{
name: 'categories',
title: 'Categories',
type: 'array',
of: [{type: 'reference', to: {type: 'category'}}],
},
{
name: 'publishedAt',
title: 'Published at',
type: 'datetime',
},
{
name: 'body',
title: 'Body',
type: 'blockContent',
},
{
name: 'extra',
title: 'extra',
type: 'blockContent',
},
],
preview: {
select: {
title: 'title',
author: 'author.name',
media: 'mainImage',
},
prepare(selection) {
const {author} = selection
return Object.assign({}, selection, {
subtitle: author && `by ${author}`,
})
},
},
}

sanity api v1 doesnt work with functions, I was using
const sanityClient = client({
dataset: "production",
useCdn: true,
projectId: "project_id",
});
which defaults to v1, but in order to use function i added a apiVersion parameter, which made it use later api version:
const sanityClient = client({
dataset: "production",
useCdn: true,
projectId: "9dz8b3g1",
apiVersion: "2021-03-25",
});

Related

Display an Array Data Referencing a Category Array with Sanity and Next.js

I'm trying to have a Category array display on the frontend with items that reference the Category below it.
I've been able to render the category titles on the page, but not the items with references to that category by doing:
export default function Menu({data}) {
const {category} = data;
return (
<section>
{category?.length > 0 &&
category
.map((category) => (
<article key={category._id}>
{category?.title &&
<h1 className="text-3xl">{category.title}</h1>}
))}
</section>
export async function getStaticProps() {
const category = await client
.fetch(
`*[_type == "category"] {
title,
"menuItems": *[_type == "menuItem" && references(^._id)] {
title,
description,
price,
...
}
}
`);
return {
props: {
data: { category }
},
}
}
I've been trying to use .map to find and return the reference data ...
Here are the Sanity schemas I have for Category and menuItem
for Category:
export default {
name: 'category',
title: 'Category',
type: 'document',
fields: [
{
name: 'title',
title: 'Title',
type: 'string',
},
],
};
for menuItem:
export default {
name: 'menuItem',
title: 'Menu Item',
type: 'document',
fields: [
{
name: 'title',
title: 'Title',
type: 'string',
},
{
name: 'category',
title: 'Category',
type: 'reference',
to: [{ type: 'category' }],
},
{
name: 'price',
title: 'Price',
type: 'number',
},
{
name: 'description',
title: 'Description',
type: 'string',
},
],
};
I know I'm doing something wrong, but can't sort it out. Can anyone help?
Thank you so much

How to custom GridJs pagination with supabase?

I'm software engineer in Cambodia.
I want to custom Grid.js pagination with supanase, but I faced a problem.
I don't know the solution because it's not in the documentation.
I'm using Nuxt 3
Please tell me how to implement.
The Code is below:
onMounted(() => {
grid.updateConfig({
columns: [
{ name: 'Avatar', id: 'avatar' },
{ name: 'name', id: 'name' },
{ name: 'gender', id: 'gender' },
{ name: 'email', id: 'email' },
{ name: 'phone', id: 'phone' },
{ name: 'address', id: 'address' },
],
pagination: {
enabled: true,
limit: 5,
server: {
url: (prev, page, limit) => `${prev}&limit=${limit}&offset=${page * limit}`
},
summary: true,
},
server: {
keepalive: true,
data: async (opt) => {
console.log(opt)
const { data: customers, error, count } = await supabase
.from('customers')
.select('id, name, gender, email, phone, address, avatar', { count: 'exact' })
.is('deleted_at', null)
.order('created_at', { ascending: false })
return {
data: customers.map((customer) => [
customer.avatar,
customer.name,
customer.gender,
customer.email,
customer.phone,
customer.address,
]),
total: count,
}
},
},
width: '100%',
search: true,
pagination: true,
fixedHeader: true,
className: {
td: 'sr-td-class',
table: 'sr-table',
},
})
grid.render(table.value)
})
I found resolve:
GridJs configuration:
onMounted(() => {
grid.updateConfig({
columns: [
{ name: 'Avatar', id: 'avatar' },
{ name: 'name', id: 'name' },
{ name: 'gender', id: 'gender' },
{ name: 'email', id: 'email' },
{ name: 'phone', id: 'phone' },
{ name: 'address', id: 'address' },
],
pagination: {
enabled: true,
limit: 5,
server: {
url: (prev, page, limit) => `${prev}&limit=${limit}&offset=${page * limit}`
},
summary: true,
},
server: {
keepalive: true,
data: async (opt) => {
console.log(opt)
const { data: customers, error, count } = await supabase
.from('customers')
.select('id, name, gender, email, phone, address, avatar', { count: 'exact' })
.is('deleted_at', null)
.order('created_at', { ascending: false })
return {
data: customers.map((customer) => [
customer.avatar,
customer.name,
customer.gender,
customer.email,
customer.phone,
customer.address,
]),
total: count,
}
},
},
width: '100%',
fixedHeader: true,
className: {
td: 'sr-td-class',
table: 'sr-table',
},
})
grid.render(table.value)
})
Then create server/api directory
after create file customers.ts in server/api/ directory
This is code in customers.ts file
import { serverSupabaseUser, serverSupabaseClient } from '#supabase/server'
export default defineEventHandler(async (event) => {
const user = await serverSupabaseUser(event)
const client = serverSupabaseClient(event)
const query = useQuery(event)
const from = query.page ? parseInt(query.page) * parseInt(query.limit) : 0
const to = query.page ? from + parseInt(query.limit) : query.limit
if (!user) {
throw createError({ statusCode: 401, message: 'Unauthorized' })
}
const { data, error, count } = await client
.from('customers')
.select('id, name, gender, email, phone, address, avatar', {
count: 'exact',
})
.is('deleted_at', null)
.order('created_at', { ascending: false })
.range(from, to)
return { customers: data, count }
})

One single mutation doesn't seem to invalidate cache

my api service
const ordersApi = createApi({
reducerPath: 'ordersApi',
baseQuery: fetchBaseQuery({ baseUrl: ROOT_ENDPOINT }),
tagTypes: ['Orders', 'Order'],
endpoints: (builder) => ({
getOrder: builder.query<TOrder, string>({
query: (id) => `/orders/${id}`,
providesTags: (result) =>
result
? [
{ type: 'Order', id: result.id },
{ type: 'Order', id: 'ORDER' },
]
: [{ type: 'Order', id: 'ORDER' }],
transformResponse: ({ _id, ...order }: TOrderResponse) => order,
}),
// some other queries
...
createOrder: builder.mutation<TOrder, TCreateOrderDto>({
query: (body) => {
return {
url: '/orders/create',
method: 'POST',
body,
};
},
invalidatesTags: (result) =>
result
? [
{ type: 'Order', id: result.id },
{ type: 'Order', id: 'ORDER' },
]
: [
{ type: 'Order', id: 'LIST' },
],
}),
// some other mutations
...
}),
});
createOrder creates a new Order object or modifies existing (by either adding new product to productsInOrder array or increasing amount property of existing array element).
The order object looks like this
{
"status": "NEW",
"vendor": {
"defaultVendor": false,
"companyName": "Mahamba",
"contactPerson": "Bahamab",
"id": "62b95b8e5603c45a7950de22"
},
"productsInOrder": [
{
"quantityToOrder": 12,
"price": 12,
"orderLimit": 12,
"product": "62b95b9c5603c45a7950de26",
"amount": 4
}
],
"orderId": 51,
"total": 48,
"id": "62ba6d60c784c34497b72652"
}
but for some reason when a new order is created neither getOrders nor getOrder endpoints get refetched and I don't understand why..
getOrder's providesTags id is exactly the same as createOrders invalidatesTags id.
Is nested objects that get mutated the problem?
How do I make sure getOrder is invalidated when a new order is created?

I Couldn't change HTTP headers in a NextJS project

As explained in the NextJs documentation: https://nextjs.org/docs/api-reference/next.config.js/headers , it is possible to configure the HTTP headers of a page using the code below, however my code is not working.
Next Example:
module.exports = {
async headers() {
return [
{
source: '/about',
headers: [
{
key: 'x-custom-header',
value: 'my custom header value',
},
{
key: 'x-another-custom-header',
value: 'my other custom header value',
},
],
},
]
},
}
My Code:
module.exports = {
async headers() {
return [
{
source: '/about',
headers: [
{
key: 'cache-control',
value: 'max-age=31536000',
},
],
},
]
},
}

Ionic2 ionic-cloud notifications on android

On Android. When app is closed and I click on notification, the app opens but the notification does not call the desired function. Why? i tried a lot of things, that didn't help...
simplified code:
frontend settings:
const cloudSettings: CloudSettings = {
'core': {
'app_id': '61d7358c'
},
'push': {
'sender_id': '1077211678670',
'pluginConfig': {
'ios': {
'alert': true,
'badge': false,
'sound': true,
'clearBadge': true
},
'android': {
'iconColor': '#1BB6EB',
'sound': true,
'clearBadge': true,
'clearNotifications': false,
'forceShow': true
}
}
}};
subscribe on even:
ngOnInit() { this.push.plugin.on('notification', data => this.notificationEvent(data)); }
function:
notificationEvent(data) { console.log('data', data) }
backend:
axios({
method: 'post',
url: 'https://api.ionic.io/push/notifications',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${config.integrations.ionic.token}`
},
data
});
data:
{ profile: 'devit1',
notification:
{ title: 'new entry',
message: 'new entry',
payload:
{ type: 1,
entryId: 2020,
id: 4191,
notId: 4191,
title: 'newEntry',
message: 'new entry, },
ios:
{ title: 'new entry',
message: 'new entry',
content_available: 0,
sound: 'default' },
android:
{ title: 'new entry',
message: 'new entry',
content_available: 0,
sound: 'default' }
},
tokens: [ 'fZ4_yY:APA91bFYxyT2gsqYvMPfwFYNJVXBwTFkk73-eohDQ_m-f_wfCiJWtUaIazG39' ] }

Resources