Meteor SEO for each route/page - meteor

Using spiderable which works great for getting pages indexed. Trying to make each route have their own meta tags with the MS-Seo package statically like this:
SeoCollection.update(
{
route_name: 'home',
route_name: 'pageone',
route_name: 'pagetwo'
},
{
$set: {
route_name: 'home',
title: '',
meta: {
'description': ''
},
og: {
'title': '',
'description' : '',
'image': '',
'url': '',
'type': ''
},
twitter: {
'card': 'summary_large_image',
'site': '',
'title': '',
'description':'',
'image': ''
}
}
},
{
$set: {
route_name: 'pageone',
title: '',
meta: {
'description': ''
},
og: {
'title': '',
'description' : '',
'image': '',
'url': '',
'type': ''
},
twitter: {
'card': 'summary_large_image',
'site': '',
'title': '',
'description':'',
'image': ''
}
}
},
{
$set: {
route_name: 'pagetwo',
title: '',
meta: {
'description': ''
},
og: {
'title': '',
'description' : '',
'image': '',
'url': '',
'type': ''
},
twitter: {
'card': 'summary_large_image',
'site': '',
'title': '',
'description':'',
'image': ''
}
}
},
{
upsert: true
}
);
I get this error: "Exception in Mongo write: TypeError: object is not a function"
I've placed this into my project root older in a file called seosettings.js
What am I doing wrong?
Solved:
Solved.
SeoCollection.update(
{
route_name: 'home'
},
{
$set: {
route_name: 'home',
title: '',
meta: {
''
},
og: {
"title": "",
"image": "",
"description": "",
"url": "",
"type":"website"
},
twitter: {
"card":"",
"site":"",
"creator": "",
"title":"",
"description":".",
"url": ""
}
}
},
{
upsert: true
}
);
Have to do it like this for each URL and placing the seosettings.js in the server folder.

I have the same error but, I solved movin the SEO.js into /lib folder
I used the code how you,
SeoCollection.update(
{
route_name: 'location',
route_name: 'router2',
route_name: 'router3',
},
{
$set: {
route_name: 'location',
title: '............',
meta: {
'description': '...........'
}
}
},
{
$set: {
route_name: 'router2',
title: '.......',
meta: {
'description': '.......'
}
}
},
{
$set: {
route_name: 'router3',
title: '.......',
meta: {
'description': '.......'
}
}
},
and Doesn't work, you must to make any SeoCollection.update for each router
SeoCollection.update(
{
route_name: 'location',
},
{
$set: {
route_name: 'location',
title: '.........',
meta: {
'description': '............'
}
}
},
{
upsert: true
},
);
SeoCollection.update(
{
route_name: 'router2',
},
{
$set: {
route_name: 'router2',
title: '.........',
meta: {
'description': '............'
}
}
},
{
upsert: true
},
);
is the Only way how Work it!

Related

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 }
})

sanity-algolia get error when using pt::text

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",
});

How to display custom icons on ng2-smart-table?

I can't display custom icons on the actions tab from ng2-smart-table. I have installed Eva Icons from Akevo Team and I want to use them. I have changed the edit button to show some custom icons but the problem is that nothing appears. On the left side of delete, a brush icon had to appear.
Here is an image with the problem:
Here is the code:
settings = {
edit: {
editButtonContent: '<nb-icon icon="brush"></nb-icon>',
saveButtonContent: '<nb-icon icon="checkmark"></nb-icon>',
cancelButtonContent: '<nb-icon icon="close-circle"></nb-icon>'
},
columns: {
device: {
title: 'Device',
sortDirection: 'asc'
},
type: {
title: 'Type',
sort: false,
filter: false
},
serialNumber: {
title: 'Serial Number'
},
status: {
title: 'Status'
}
}
};
Try this :
settings = {
hideSubHeader: true,
actions: {
custom: [
{
name: 'edit',
title: '<nb-icon icon="brush"></nb-icon>'
},
{
name: 'save',
title: '<nb-icon icon="checkmark"></nb-icon>'
},
{
name: 'cancel',
title: '<nb-icon icon="close-circle"></nb-icon>'
}
],
add: false,
edit: false,
delete: false
}
...
};
hope this works for you!
Also you can use other icons sets like material icons, just add it to your project and then change your settings like:
settings = {
edit: {
editButtonContent: '<span class="material-icons">mode_edit</span>',
saveButtonContent: '<span class="material-icons">check_circle</span>',
cancelButtonContent: '<span class="material-icons">cancel</span>'
},
/* ... */
}
settings = {
hideSubHeader: true,
sort: true,
actions: {
position: 'left',
add: false,
edit: false,
delete: false,
select: false,
custom: [
{
name: 'viewRecord',
type: 'html',
title: '<i class="far fa-file-alt" title="View Record"></i>',
},
{
name: 'editRecord',
type: 'html',
title: '<i class="far fa-edit" title="Edit Record"></i>',
},
],
},
columns: {
column1: {
title: 'Column 1',
type: 'string',
width: '35%',
},
column2: {
title: 'Column 2',
type: 'string',
},
column3: {
title: 'Column 3',
type: 'string',
},
},
};
I found this thread:
https://github.com/akveo/ng2-smart-table/issues/1034
And so as mentioned in the last comment:
temporarily use the old nebular-icons
https://github.com/akveo/nebular-icons/tree/master/src/icons
I downloaded the required icon's SVG and added them as:
settings = {
edit: {
editButtonContent: '<img src="assets/images/nb-edit.svg" width="40" height="40" >'
. . .
}
. . .
}
Works well enough.
let newSettings = {
mode: "external",
actions: {
add: false,
edit: false,
delete: false,
position: 'right'
},
hideSubHeader: true,
add: {
addButtonContent: '<i class="nb-plus"></i>',
},
edit: {
editButtonContent: '<img src="assets/images/icons/outline/settings-2-outline.svg" width="20" height="20" >',
},
delete: {
deleteButtonContent: '<img src="assets/images/icons/outline/trash-2-outline.svg" width="20" height="20" >',
confirmDelete: true,
},
}

Extjs store don't fill grid lines

You can see my code about grid.
Here, Window opens but there is not any value in my grid.
Could you please help?
My php returns JSON encode blow:
{"results":3,"disPath":"","success":"true","rows":[{"id":"1","faz":"Faz1"},{"id":"2","faz":"Faz2"},{"id":"3","faz":"Faz3"}]}
Code
Ext.define('MyDesktop.GridFazlar', {
extend: 'Ext.ux.desktop.Module',
requires: [
'Ext.data.ArrayStore',
'Ext.util.Format',
'Ext.grid.Panel',
'Ext.grid.RowNumberer'
],
id:'grid-fazlar',
init : function(){
this.launcher = {
text: 'Fazlar',
iconCls:'icon-grid'
};
},
createWindow : function(){
var desktop = this.app.getDesktop();
var win = desktop.getWindow('grid-fazlar');
if(!win){
var fazlarGridStore = new Ext.data.JsonStore({
root: 'rows',
autoLoad: true,
totalProperty: 'results',
remoteSort: true,
proxy: new Ext.data.HttpProxy({
url: 'phps/gridPhasesLoader.php',
actionMethods: {
create : 'POST',
read : 'POST',
update : 'POST',
destroy: 'POST'
},
}),
baseParams:{
depth: '2',
parentId: '2',
proccess: 'callGrid',
},
fields: [{
name :'id'
},{
name :'faz'
},
//{
]
});
win = desktop.createWindow({
id: 'grid-fazlar',
title:'Fazlar',
width:740,
height:480,
iconCls: 'icon-grid',
animCollapse:false,
constrainHeader:true,
layout: 'fit',
listeners:{
beforeshow: function(){
fazlarGridStore.proxy.extraParams = {
depth: '2',
parentId: '2',
proccess: 'callGrid',
};
}
},
items: [
{
border: false,
xtype: 'grid',
listeners: {
celldblclick : function() {
alert('Deneme');
},
},
contextMenu: new Ext.menu.Menu({
items:[
{
id:'grid-fazlar_menu_denemebutton',
text: 'DenemeButonu',
listeners: {
click: function(){
alert('sssss');
}
}
}
]
}),
store:fazlarGridStore,
columns: [
new Ext.grid.RowNumberer(),
{
text: "ID",
//flex: 1,
width: 70,
sortable: true,
dataIndex: 'id'
},{
text: "Faz",
//flex: 1,
width: 70,
sortable: true,
dataIndex: 'faz'
},
]
}
],
tbar:[{
text:'Add Something',
tooltip:'Add a new row',
iconCls:'add'
}, '-', {
text:'Options',
tooltip:'Modify options',
iconCls:'option'
},'-',{
text:'Remove Something',
tooltip:'Remove the selected item',
iconCls:'remove'
}]
});
}
return win;
},
statics: {
getDummyData: function () {
return [
['Faz1','06/06/2011','15/08/2010','19/12/2010'],
['Faz2','01/10/2010','15/11/2010','29/11/2011'],
['Faz3','16/11/2010','16/12/2010','14/02/2011'],
['Faz4','19/03/2011','20/03/2011','18/06/2011'],
['Faz5','21/03/2011','20/05/2011','18/08/2011'],
['Faz6','21/05/2011','05/07/2011','18/09/2011'],
['Faz7','06/07/2011','04/09/2011','06/12/2011'],
['Faz8','30/09/2011','30/10/2011','29/12/2011'],
];
}
}
});
Your Json has a custom root : 'rows'. You must configure your datareader to take this into account:
proxy: {
type: 'ajax',
url: 'phps/gridPhasesLoader.php',
actionMethods: {
create : 'POST',
read : 'POST',
update : 'POST',
destroy: 'POST'
},
reader: {
type: 'json',
root: 'rows'
}
},

Sencha Touch button has no response to Tap event

i'm new in sencha touch and i'm having a weird problem with a button. I'm using mvc, and i have:
Adduserview.js
Ext.define('App.view.Adduserview', {
extend: 'Ext.form.Panel',
xtype: 'adduserview',
requires: ['Ext.form.FieldSet','Ext.field.Select','App.store.Companies'],
config: {
id: 'userform',
items: [
{
xtype: 'fieldset',
title: 'Details',
items:[
{
xtype: 'textfield',
name: 'userName',
label: 'Name'
},
{
xtype: 'textfield',
name: 'userLastname',
label: 'Lastname'
},
{
xtype: 'textfield',
name: 'userNumber',
label: 'Number'
}
]
},
{
xtype: 'fieldset',
title: 'Links',
items: {
xtype: 'selectfield',
label: 'Company',
store: Ext.create('App.store.Companies'),
displayField: 'companyName',
valueField: 'companyName'
}
},
{
xtype: 'button',
text: 'Send',
id: 'adduserButton'
}
]
}
});
Adduser.js
Ext.define('App.controller.Adduser', {
extend: 'Ext.app.Controller',
config: {
refs:{
userform: '#userform'
},
control: {
'#adduserButton': {
tap: function(){
var valuesUser = this.getUserform().getValues();
console.log(valuesUser);
if (notNull(valuesUser.userName) && notNull(valuesUser.userLastname) && notNull(valuesUser.userNumber)){
Ext.Ajax.request({
url: 'http://server.com/insertUser.php',
params: valuesUser,
method: 'post',
success: function(response){
var text = response.responseText;
Ext.Msg.alert('Success', text);
},
failure : function(response) {
Ext.Msg.alert('Error','Error while submitting the form');
console.log(response.responseText);
}
});
this.getUserform().reset();
}
else{
Ext.Msg.alert('Error', 'All the fields are necessary');
}
}
}
}
}
});
function notNull(a) {
if(a!="" && !(a.match(/^\s+$/))){
return true;
}
else{
return false;
}
};
The problem is that the button does not work, it just does nothing when pressed, and i have other two FormPanels exactly like that but with different data, and each of them has a controller just like the one i showed but with different code in the tap function, and they work. I noticed that when i see the scripts that are loaded in chrome, the Adduser.js is not there, so i guess thats the reason its not working, but im not sure why its not loading.
By the way i added the controllers to App.js.
Thanks for the help.
Change your refs to
refs:{
userButton: '#adduserButton'
}
And the Control As
control: {
userButton: {
Hope this helps you
update your controoler code with
Ext.define('App.controller.Adduser', {
extend: 'Ext.app.Controller',
config: {
refs:{
userform: '#userform'
}
},
init: function () {
this.control({
'#adduserButton': {
tap: function(){
var valuesUser = this.getUserform().getValues();
console.log(valuesUser);
if (notNull(valuesUser.userName) && notNull(valuesUser.userLastname) && notNull(valuesUser.userNumber)){
Ext.Ajax.request({
url: 'http://server.com/insertUser.php',
params: valuesUser,
method: 'post',
success: function(response){
var text = response.responseText;
Ext.Msg.alert('Success', text);
},
failure : function(response) {
Ext.Msg.alert('Error','Error while submitting the form');
console.log(response.responseText);
}
});
this.getUserform().reset();
}
else{
Ext.Msg.alert('Error', 'All the fields are necessary');
}
}
}
});
},
}
});
Add
controllers: [
'App.controller.Adduser',
],
in app

Resources