-
Notifications
You must be signed in to change notification settings - Fork 46
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Versioning of Content types with Unique field #6
Comments
Hi thanks for reporting, we already know about this issue. It's know issue by design. Right now it is not priority for us, but we will look at it in future. |
Hi, I was just wondering if there is any progress on this one? Thx |
Hi, not right now, we are focusing on content internalization versioning. |
Hey. This is a pity as UID fields are needed to work with Slugify and generate friendly URLs. It seems very important to me that they can work together. For now, I'll prioritize working with the slug system and wait until the versioning plugin is working along with it. |
Hey, just wanted to let you guys know : I was very excited about your plugin, but this bug is makin it unusable for me... Basically all my content types have Unique Fields. I understand you have other stuff to address and that the plugin is under developpement, but for me fixing this should be a priority. |
Hi, we are trying to find solution with Strapi, because this problem is under databaselayer (unque is setted up in DB not in Strapi) so we are still trying to find some workaround. If you have any ideas just write it here it can help :) Thanks! |
Good to know you are working on it! :D |
Any update on fixing this bug, please? |
Hello, @martincapek do you have any updates about this issue?! |
@martincapek any news on this issue? In general - do you have advice on how to work with "slugs" when using this package? I want to achieve the fairly common use case to have my urls like [domain]/[content-type]/[slug OR id] on my consumer site. I can't keep a slug on my content types because of this issue, and I can't use the entry's id either since it "changes" with every new saved version... Surely, someone must have had this kind of problem before me. How did you achieve this? |
I also encountered the same problem,I hope to solve it |
@martincapek I haven't looked into this, but couldn't you add some sort of "magic prefix" to the ids stored in the database? "some_id" becomes "_content_versioning#!randomstring!#__some_id" when saved in the database and when read back, just remove it based on a regex? |
@martincapek Thank you for contributing to strapi and building this plugin. However, featuring uid field is a very common practice for strapi projects. Please consider bringing this fix. In our understanding, most of the collections which need this plugin will have uid fields (slug, url, uuid). I am not sure what is your implentation plans for this, but you could create a separate collection for collections this module is enabled. Some other And instead of creating a whole new entry for the pages collection, create new versions in that additional table. |
Hey @martincapek, What about a compound ID with the slug + version? |
Hello everyone, I will now be taking over the maintenance of this plugin. Over the next few weeks, our main priority will be to eliminate the need for patching the plugin. Once that is successfully completed, I assume that we shift our focus towards implementing this feature. |
Hello @omikulcik , any plan on this feature being developed? Thanks for your work! |
Hi @Daserec, it is definitely on the roadmap but we haven't yet decided on when to ship it. |
Hey - did this ever make it out of the backlog? If it's not happening, then I am going to have to set aside the content-versioning plugin and write something - maybe like a simple plugin that will deploy a published document version between 2 strapi instances. My app is fundamentally dependent on unique slugs. Figured I'd check in case you were about to knock it out, but I am guessing that your priorities are firmly elsewhere. |
Hi @anderslars, sorry to hear that. Our priority right now is to finish support for relations so versioning of unique fields will not be shipped earlier than Q1 of 2024. Just to provide more information, Strapi said that V5 will feature upgraded draft and publish including content versioning so this will probably resolve your issues. However, it can take some time till v5 is released. |
@omikulcik is there any way to exclude UIDs (slugs) from being versioned? I.e. not throw an error, but just ignore them? |
wait for it 🙏 |
Hello everyone, I believe that most of you have already given up on this, mainly because in the next version this function will be in the core. anyway I tried to write something that would work for me, I don't know if it's the most elegant way to do it, and sure the code is a bit spaghetti, but you get the idea. I followed some tips from here https://docs.strapi.io/dev-docs/configurations/functions so I added a text field called 'slug' (not mandatory) basically this code generates the slug based on the title It's an ugly solution, but for my context it works. export default {
/**
* An asynchronous register function that runs before
* your application is initialized.
*
* This gives you an opportunity to extend code.
*/
register(/*{ strapi }*/) {},
/**
* An asynchronous bootstrap function that runs before
* your application gets started.
*
* This gives you an opportunity to set up your data model,
* run jobs, or perform some special logic.
*/
bootstrap({ strapi }) {
strapi.db.lifecycles.subscribe({
models: ["api::article.article"], // listen to events for the article model
beforeCreate: async ({ params }) => {
const { data } = params;
// Only generate slug if not provided by user
if (!data.slug && data.title) {
let newSlug = slugify(data.title);
let isUnique = await checkPublishedSlugUnique(strapi, newSlug);
// Ensure slug is unique using versionNumber if provided
if (!isUnique && data.versionNumber) {
newSlug = `${newSlug}-v${data.versionNumber}`;
isUnique = await checkPublishedSlugUnique(strapi, newSlug);
}
// Final check
if (!isUnique) {
let version = data.versionNumber || 1;
while (!isUnique) {
version += 1;
newSlug = `${newSlug}-v${version}`;
isUnique = await checkPublishedSlugUnique(strapi, newSlug);
}
}
data.slug = newSlug;
} else if (data.slug) {
let isUnique = await checkPublishedSlugUnique(strapi, data.slug);
// Ensure slug is unique using versionNumber if provided
if (!isUnique && data.versionNumber) {
data.slug = `${data.slug}-v${data.versionNumber}`;
isUnique = await checkPublishedSlugUnique(strapi, data.slug);
}
// Final check
if (!isUnique) {
let version = data.versionNumber || 1;
while (!isUnique) {
version += 1;
data.slug = `${data.slug}-v${version}`;
isUnique = await checkPublishedSlugUnique(strapi, data.slug);
}
}
}
},
beforeUpdate: async ({ params }) => {
const { data, where } = params;
const id = where.id;
// Only generate slug if not provided by user
if (!data.slug && data.title) {
let newSlug = slugify(data.title);
let isUnique = await checkPublishedSlugUnique(strapi, newSlug, id);
// Ensure slug is unique using versionNumber if provided
if (!isUnique && data.versionNumber) {
newSlug = `${newSlug}-v${data.versionNumber}`;
isUnique = await checkPublishedSlugUnique(strapi, newSlug, id);
}
// Final check
if (!isUnique) {
let version = data.versionNumber || 1;
while (!isUnique) {
version += 1;
newSlug = `${newSlug}-v${version}`;
isUnique = await checkPublishedSlugUnique(strapi, newSlug, id);
}
}
data.slug = newSlug;
} else if (data.slug) {
let isUnique = await checkPublishedSlugUnique(strapi, data.slug, id);
// Ensure slug is unique using versionNumber if provided
if (!isUnique && data.versionNumber) {
data.slug = `${data.slug}-v${data.versionNumber}`;
isUnique = await checkPublishedSlugUnique(strapi, data.slug, id);
}
// Final check
if (!isUnique) {
let version = data.versionNumber || 1;
while (!isUnique) {
version += 1;
data.slug = `${data.slug}-v${version}`;
isUnique = await checkPublishedSlugUnique(strapi, data.slug, id);
}
}
}
},
});
},
};
/**
* Function to convert text to a URL-friendly slug
* Replaces spaces with hyphens, removes non-word characters,
* and trims extra hyphens
*/
export function slugify(text) {
return text
.toString()
.toLowerCase()
.replace(/\s+/g, '-') // Replace spaces with -
.replace(/[^\w\-]+/g, '') // Remove all non-word chars
.replace(/\-\-+/g, '-') // Replace multiple - with single -
.replace(/^-+/, '') // Trim - from start of text
.replace(/-+$/, ''); // Trim - from end of text
}
/**
* Function to check if the slug is unique among published articles
* Optionally excludes a specific article by ID
*/
async function checkPublishedSlugUnique(strapi, slug, id = null) {
const query: { slug: any; published_at: { $ne: any; }; id?: { $ne: any; } } = { slug, published_at: { $ne: null } }; // only check published articles
if (id) {
query.id = { $ne: id }; // exclude current record
}
const existingEntry = await strapi.db.query('api::article.article').findOne({ where: query });
return !existingEntry;
};
|
Bug report
Describe the bug
If a content type has a field declared as "Unique Field" in the Content type builder, saving new versions after the initial v1 fails with
System
The text was updated successfully, but these errors were encountered: