Strapi V4 slugify plugin not seeing the created models - next.js

I just started playing around with strapi using it for my next project with nextjs and i got stuck a little bit on the slug part.
I have installed the slugify plugin in the strapi admin panel, restarted the server and in the roles(permissions) section i enabled it for both authenticated and public roles.After this i created a collection type name Blog. I added some fields to it title, content, cover, slug(short text).
After this i created some blog posts and listed them out on the page. The problem began when i tried to access the blog post using the slug:
`${process.env.NEXT_PUBLIC_STRAPI_URL}/slugify/slugs/blog/${slug}?populate=*`,
The url is ok as the slug part is populated and is the value that i have given the slug field when created the blog post. The error that i get is the following:
blog model name not found, all models must be defined in the settings and are case sensitive.
The problem is that the slugify plugin is trying to match the model name to the existing ones and its not finding it so throws this error.
I started to dig a little bit deeper and began to console log in the slugify plugin inside strapi node_module:
module.exports = ({ strapi }) => ({
async findSlug(ctx) {
const { models } = getPluginService(strapi, 'settingsService').get();
const { modelName, slug } = ctx.request.params;
const { auth } = ctx.state;
console.log(getPluginService(strapi, 'settingsService').get());
isValidFindSlugParams({
modelName,
slug,
models,
});
As you can see it should container a models param aswell that should contain all the current models created in strapi. However the model paramateres comes back as an empty object, its like the plugin does not see the created collections.
The collections were created after the instalation of the slugify plugin.
I am developing on localhost using sqlite with strapi v4.
Any ideas why is this happening? Anyone else encountered this error?
Thanks,
Trix

Firstly, you have to install Slugify plugin.
After that you have to do some config steps.
To do all of that:
As you mentioned, you found Slugify folder in node_modules so you can skip first step:
npm install strapi-plugin-slugify
in the ./config/ folder create a file named plugins.js
./config/plugins.js
Paste this code there it will let you see the endpoint path in the right side of the screen:
module.exports = ({ env }) => ({
// ...
slugify: {
enabled: true,
config: {
contentTypes: {
blog: { //write what your collection type's name is this case we should use "blog"
field: "slug",
references: "title",
},
},
},
},
// ...
});
The endpoint example
fetcher(`${API}/slugify/slugs/blog/${slug}`)

Related

Catch all dynamic route in Next.js results in unwanted link in sitemap using next-sitemap package

In my Next.js application I am using the catch all functionality of dynamic routing. When I use the package next-sitemap for creating a sitemap I see in the file sitemap-0.xml there is a link like:
https://example.com/posts/1/2/3/4/5.
I believe this corresponds with the getStaticPaths function in the file [...posts.js] like below:
export async function getStaticPaths() {
const dbRows = await getPostIds();
const postIds = dbRows.map(post => post['post_id'])
return {
paths: [{params: {postId: postIds}}],
fallback: 'blocking',
}
}
Luckily the next-sitemap package offers to exclude pages. So this might be a solution for me. Though somehow I have the feeling the solution is in Next.js itself or the next-sitemap package itself besides using the exclude config.
I solved the issue by providing all path parameters instead of just an array of post ids.
Solution:
paths:
[{params: {postId: ['Python', '1']}},
{params: {postId: ['Java', '2']}}]

Where should I store JSON file and fetch data in Next.JS whenever I need?

Project:
I am working on an E-commerce application and it has more than 1,600 products and 156 categories.
Problem:
Initially, on the first product page, 30 products will be fetched (due to the page limitation), but on the left sidebar, I need filters that will be decided on the basis of tags of all 1,600 products. So that's why I need all the products in the first fetch and then I will extract common tags by looping over all the products and immediately show them on the sidebar.
What do I want?
I am not sure but I think it would be the best solution if I generate a JSON file containing all the products and store it somewhere, where I can fetch just hitting the URL using REST API in Next JS (either in getServerSideProps or getStaticProps).
Caveat:
I tried by storing JSON file in ./public directory in next js application, it worked in localhost but not in vercel.
Here is the code I wrote for storing JSON file in ./public directory:
fs.writeFileSync("./public/products.json", JSON.stringify(products, null, 2)); //all 1,600 products
One solution it to fetch it directly from front-end (if the file is not too big) otherwise, for reading the file in getServerSideProps you will need a custom webpack configuration.
//next.config.js
const path = require("path")
const CopyPlugin = require("copy-webpack-plugin")
module.exports = {
target: "serverless",
future: {
webpack5: true,
},
webpack: function (config, { dev, isServer }) {
// Fixes npm packages that depend on `fs` module
if (!isServer) {
config.resolve.fallback.fs = false
}
// copy files you're interested in
if (!dev) {
config.plugins.push(
new CopyPlugin({
patterns: [{ from: "content", to: "content" }],
})
)
}
return config
},
}
Then you can create a utility function to get the file:
export async function getStaticFile(file) {
let basePath = process.cwd()
if (process.env.NODE_ENV === "production") {
basePath = path.join(process.cwd(), ".next/server/chunks")
}
const filePath = path.join(basePath, `file`)
const fileContent = await fs.readFile(filePath, "utf8")
return fileContent
}
There is an open issue regarding this:
Next.js API routes (and pages) should support reading files

How do I use cordova firebase.dynamiclinks plugin in Ionic 4?

I want to use Cordova Firebase Dynamiclinks plugin : https://github.com/chemerisuk/cordova-plugin-firebase-dynamiclinks#installation in my Ionic 4 App.
There is an Ionic-native-plugin usage for this too : npm install #ionic-native/firebase-dynamic-links and usage :
import { FirebaseDynamicLinks } from '#ionic-native/firebase-dynamic-links/ngx';
constructor(private firebaseDynamicLinks: FirebaseDynamicLinks) { }
...
this.firebaseDynamicLinks.onDynamicLink()
.subscribe((res: any) => console.log(res), (error:any) => console.log(error));
Issue is : I want to use createDynamicLink(parameters) method available in Cordova Firebase Dynamiclinks plugin but Ionic-native-plugin says
Property 'createDynamicLink' does not exist on type 'FirebaseDynamicLinks'.
Therefore, I need to use Cordova Firebase Dynamiclinks directly and I tried doing using it like
import { cordova } from '#ionic-native/core';
...
cordova.plugins.firebase.dynamiclinks.createDynamicLink({
link: "https://google.com"
}).then(function(url) {
console.log("Dynamic link was created:", url);
});
But got error
Property 'plugins' does not exist on type '(pluginObj: any, methodName: string, config: CordovaOptions, args: IArguments | any[]) => any'.
Also tried removing import
cordova.plugins.firebase.dynamiclinks.createDynamicLink({
link: "https://google.com"
}).then(function(url) {
console.log("Dynamic link was created:", url);
});
And got this
Property 'firebase' does not exist on type 'CordovaPlugins'.
What is the correct usage of cordova plugins?
Update
Ionic-native-plugin now contains all the methods available in Cordova Firebase Dynamiclinks plugin.
I believe this is more fitting of a comment, but I don't quite have the reputation for it yet.
Currently, there is a PR open in the #ionic-team/ionic-native repo (here). This exposes the extra methods, but until then you can use the original repo here to get your desired effect. In order to install the repo you will have to follow the directions in the Developer guide here. Cheers!
I have developed an ionic 5 app that uses Firebase Dynamic Links and it works great but it took some effort. I watched videos to understand how Firebase Dynamic Links work but there is certainly much that is not shown.
To answer the original question you can always manually create a dynamic link which is what I do in our solution. We created a dynamic link that would help users onboard (register an account). Our dynamic link has custom onboardingId which originates from the backend process and the link is presented to the user via SMS text message.
This is in app.component.ts constructor
Here is some code that happens when the user clicks the dynamic link:
// Handle the logic here after opening the app (app is already installed) with the Dynamic link
this.firebaseDynamicLinks.onDynamicLink().subscribe((res: any) => {
console.log('app was opened with dynamic link');
console.log(res);
/* This only fires on subsequent calls and not on app start 20220208 STR
console.log(JSON.stringify(res)); //"{"deepLink":"https://localhost/onboard?onboardingId=8ed634b0-53b7-4a0f-b67e-12c06019982a","clickTimestamp":1643908387670,"minimumAppVersion":0}"
var dynamicLink = JSON.parse(JSON.stringify(res));
var deepLink = dynamicLink.deepLink;
console.log(deepLink);
if (deepLink.indexOf("onboard")>=0){
this.isOnboarding = true;
}
alert("deepLink ="+ deepLink);
*/
}, (error:any) => {
console.log(error)
});
I originally thought that Firebase handles all of the magic if the user doesn't have the app installed. I was wrong! You MUST also handle the code to pickup the dynamic link after the app is installed.
The code below will read the dynamic link from the clipboard and survives the app install process. Placed in app.component.ts ngOnInit().
this.platform.ready().then(() => {
this.firebaseDynamicLinks.getDynamicLink().then((data) => {
//added 20220208 STR try to help open the deep link if app is just installed
if (data != null) {
console.log(JSON.stringify(data));
//alert("initializeApp():"+JSON.stringify(data));
var dynamicLink = JSON.parse(JSON.stringify(data));
var deepLink = dynamicLink.deepLink;
console.log("initializeApp():"+deepLink);
if (deepLink != "") {
if (deepLink.indexOf("onboard")>=0){
this.isOnboarding = true;
this.deepLinkToOnboard(deepLink);
}
}
}
});}
So to handle dynamic links after you have the Firebase plugin installed, you must have two sections of code; one for handling if the app is already installed and another for handling the dynamic link if the app is not installed.

Nextjs export clear "out" folder

I'm working with nextjs and this example https://github.com/zeit/next.js/tree/master/examples/with-static-export
in next.config.js i have code:
module.exports = {
async exportPathMap(defaultPathMap, { dev, dir, outDir, distDir, buildId, incremental }) {
// we fetch our list of posts, this allow us to dynamically generate the exported pages
const response = await fetch(
'https://jsonplaceholder.typicode.com/posts?_limit=3'
)
const postList = await response.json()
// tranform the list of posts into a map of pages with the pathname `/post/:id`
const pages = postList.reduce(
(pages, post) =>
Object.assign({}, pages, {
[`/post/${post.id}`]: { page: '/post/[id]' },
}),
{}
)
// combine the map of post pages with the home
return Object.assign({}, pages, {
'/': { page: '/' },
})
},
}
Its fetch 3 posts and generate files - [id].html - its great!
But now i need to fetch new post and build page only for this new post but commad next export remove all files from out and create only one post.
What i need to do to keep old post and add new one on next export?
Example:
First next export with request for 3 posts from api
generate 3 post in folder "out"
change api url and run next export for 1 new post
summary i have 3 old post pages and 1 new in my "out" directory
How to do that?
Next can't do this out of the box, but you can set it up to do so. First, you'll need a system (database) of which pages have already been built. Second, you'll need some method of communicating with that database (api) to ask which pages should be built (eg, send over a list of pages and the api responds telling you which ones have not yet bene built). Then, tell your exportPathMap which pages to build. And finally, move your built pages out of out and into a new final/public directory.
By default, Next will build/export anything in the pages directory plus anything you set in exportPathMap, and put all of those in the out directory. You can override what it builds by passing a custom exportPathMap, and how you handle what goes into the out directory is up to you, so you can move those files to a different actual public directory and merge them with the old files.

Vue Firebase / Firestore Duplicates

I am trying to go through a tutorial (link below) to learn vue and firebase. There is a main dashboard page with a list of components, and I have gotten that to display a list of employees. Then there is a view employee component. When I started to build that, and just loaded data, I started getting this error:
Uncaught FirebaseError {code: "app/duplicate-app", message: "Firebase:
Firebase App named '[DEFAULT]' already exists (app/duplicate-app).",
name: "[DEFAULT]", stack: "[DEFAULT]: Firebase: Firebase App named
'[DEFAULT]…0)↵ at fn (http://localhost:8081/app.js:89:20)"}
The firebase code I added to view employee is as follows:
import db from "./firebaseInit.js";
export default {
name: "view-employee",
data() {
return {
employee_id: null,
name: null,
dept: null,
position: null
};
},
beforeRouteEnter(to, from, next) {
db
.collection("employees")
.where("employee_id", "==", to.params.employee_id),
get().then(querySnapShot => {
querySnapShot.forEach(doc => {
next(vm => {
vm.employee_id = doc.data().employee_id
vm.name = doc.data().name
vm.dept = doc.data().dept
vm.position = doc.data().position
})
});
});
}
};
When I comment out this script on the view employee page, the error goes away. From what I can tell, I have done everything the same as the tutorial in the video, and as my buddy who did the same project.
There is also a warning, which may be related, which states as follows:
There are multiple modules with names that only differ in casing. This
can lead to unexpected behavior when compiling on a filesystem with
other case-semantic. Use equal casing. Compare these module
identifiers: *
/Users/jdurell/code/employeemanager/node_modules/babel-loader/lib/index.js!/Users/jdurell/code/employeemanager/src/components/FirebaseInit.js
I am working on this tutorial / project:
https://www.youtube.com/watch?v=cjEzK4me1k8&index=4&list=PLillGF-RfqbYsOOycB67Raf9dwmL6Y31M
Nemesv had the correct answer. It was a casing issue. I had the issue FirebaseInit on the other component. I changed that to firebaseInit so it was the same case on both components, and the error resolved. Thanks!

Resources