Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import template from './werkl-blog-list.html.twig';
import './werkl-blog-list.scss';

const { Mixin } = Shopware;
const { Mixin, Context } = Shopware;
const Criteria = Shopware.Data.Criteria;
const { cloneDeep } = Shopware.Utils.object;

export default {
template,
Expand Down Expand Up @@ -43,6 +44,10 @@ export default {
return this.repositoryFactory.create('werkl_blog_category');
},

pageRepository() {
return this.repositoryFactory.create('cms_page');
},

dateFilter() {
return Shopware.Filter.getByName('date');
},
Expand Down Expand Up @@ -111,5 +116,140 @@ export default {
openSponsorPage() {
window.open('https://github.com/sponsors/7underlines', '_blank');
},

async onDuplicate(blogEntry) {
this.isLoading = true;

try {
// Create criteria to load the full blog entry with all associations
const criteria = new Criteria();
const sortCriteria = Criteria.sort('position', 'ASC', true);

criteria
.addAssociation('blogCategories')
.addAssociation('tags')
.addAssociation('blogAuthor')
.getAssociation('cmsPage')
.getAssociation('sections')
.addSorting(sortCriteria)
.addAssociation('backgroundMedia')
.getAssociation('blocks')
.addSorting(sortCriteria)
.addAssociation('backgroundMedia')
.addAssociation('slots');

// Load the full blog entry
const fullBlogEntry = await this.blogEntryRepository.get(
blogEntry.id,
Context.api,
criteria
);

// Create a new CMS page (deep copy of the original)
let newCmsPage = null;
if (fullBlogEntry.cmsPage) {
newCmsPage = this.pageRepository.create();
const originalPage = fullBlogEntry.cmsPage;

// Copy basic page properties
newCmsPage.name = `${originalPage.name} (Copy)`;
newCmsPage.type = originalPage.type;
newCmsPage.locked = originalPage.locked;
newCmsPage.config = cloneDeep(originalPage.config);

// Deep copy sections - use cloneDeep and then assign new IDs
if (originalPage.sections && originalPage.sections.length > 0) {
const clonedSections = cloneDeep(originalPage.sections);
newCmsPage.sections = clonedSections.map(section => {
// Remove the ID so Shopware creates a new one
delete section.id;
delete section.cmsPageId;
delete section.versionId;

if (section.blocks) {
section.blocks = section.blocks.map(block => {
delete block.id;
delete block.sectionId;
delete block.versionId;

if (block.slots) {
block.slots = block.slots.map(slot => {
delete slot.id;
delete slot.blockId;
delete slot.versionId;
return slot;
});
}

return block;
});
}

return section;
});
}

// Save the new CMS page first
await this.pageRepository.save(newCmsPage, Context.api);
}

// Create the new blog entry
const newBlogEntry = this.blogEntryRepository.create();

// Copy properties from original blog entry
newBlogEntry.title = `${fullBlogEntry.title} (Copy)`;
newBlogEntry.slug = null; // Will be auto-generated from title
newBlogEntry.teaser = fullBlogEntry.teaser;
newBlogEntry.metaTitle = fullBlogEntry.metaTitle;
newBlogEntry.metaDescription = fullBlogEntry.metaDescription;
newBlogEntry.authorId = fullBlogEntry.authorId;
newBlogEntry.publishedAt = null; // Set to null for inactive entry
newBlogEntry.active = false; // Set as inactive by default
newBlogEntry.detailTeaserImage = fullBlogEntry.detailTeaserImage;
newBlogEntry.mediaId = fullBlogEntry.mediaId;
newBlogEntry.cmsPageId = newCmsPage ? newCmsPage.id : null;

// Copy categories
if (fullBlogEntry.blogCategories && fullBlogEntry.blogCategories.length > 0) {
fullBlogEntry.blogCategories.forEach(category => {
newBlogEntry.blogCategories.add(category);
});
}

// Copy tags
if (fullBlogEntry.tags && fullBlogEntry.tags.length > 0) {
fullBlogEntry.tags.forEach(tag => {
newBlogEntry.tags.add(tag);
});
}

// Save the new blog entry
await this.blogEntryRepository.save(newBlogEntry, Context.api);

// Show success notification
this.createNotificationSuccess({
message: this.$tc('werkl-blog.list.notification.duplicateSuccess', 0, {
title: fullBlogEntry.title,
}),
});

// Refresh the list
await this.getList();

// Navigate to the duplicated entry
this.$router.push({
name: 'blog.module.detail',
params: { id: newBlogEntry.id },
});

} catch (error) {
this.createNotificationError({
message: this.$tc('werkl-blog.list.notification.duplicateError'),
});
console.error('Error duplicating blog entry:', error);
} finally {
this.isLoading = false;
}
},
},
};
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,16 @@
</template>
{% endblock %}

{% block werkl_blog_list_grid_actions %}
<template #actions="{ item }">
{% block werkl_blog_list_grid_actions_duplicate %}
<sw-context-menu-item @click="onDuplicate(item)">
{{ $tc('werkl-blog.list.contextMenuDuplicate') }}
</sw-context-menu-item>
{% endblock %}
</template>
{% endblock %}

</sw-entity-listing>
{% endblock %}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,18 @@
"buttonAddBlogEntry": "Blog Eintrag erstellen",
"buttonSponsor": "Entwicklung unterstützen",
"messageEmpty": "Keine Einträge vorhanden",
"buttonDuplicate": "Duplizieren",
"contextMenuDuplicate": "Duplizieren",
"notification": {
"duplicateSuccess": "Blog Eintrag \"{title}\" wurde erfolgreich dupliziert.",
"duplicateError": "Fehler beim Duplizieren des Blog Eintrags."
},
"table": {
"title": "Titel",
"active": "Aktiv",
"author": "Autor",
"publishedAt": "Veröffentlicht am"
"publishedAt": "Veröffentlicht am",
"actions": "Aktionen"
}
},
"detail": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,18 @@
"buttonAddBlogEntry": "Create blog entry",
"buttonSponsor": "Support development",
"messageEmpty": "No blog entries ...",
"buttonDuplicate": "Duplicate",
"contextMenuDuplicate": "Duplicate",
"notification": {
"duplicateSuccess": "Blog entry \"{title}\" has been successfully duplicated.",
"duplicateError": "Error duplicating blog entry."
},
"table": {
"title": "Title",
"active": "Active",
"author": "Author",
"publishedAt": "Published at"
"publishedAt": "Published at",
"actions": "Actions"
}
},
"detail": {
Expand Down