Added support for creating new tags when bulk editing posts
refs https://github.com/TryGhost/Team/issues/2922
This commit is contained in:
parent
76fae2a724
commit
788aa34c8b
@ -105,10 +105,49 @@ export default class PostsContextMenu extends Component {
|
||||
*addTagToPostsTask(tags) {
|
||||
const updatedModels = this.selectionList.availableModels;
|
||||
|
||||
yield this.performBulkEdit('addTag', {tags: tags.map(tag => tag.id)});
|
||||
|
||||
yield this.performBulkEdit('addTag', {
|
||||
tags: tags.map((t) => {
|
||||
return {
|
||||
id: t.id,
|
||||
name: t.name,
|
||||
slug: t.slug
|
||||
};
|
||||
})
|
||||
});
|
||||
this.notifications.showNotification(this.#getToastMessage('tagsAdded'), {type: 'success'});
|
||||
|
||||
const serializedTags = tags.toArray().map((t) => {
|
||||
return {
|
||||
...t.serialize({includeId: true}),
|
||||
type: 'tag'
|
||||
};
|
||||
});
|
||||
|
||||
// Destroy unsaved new tags (otherwise we could select them again)
|
||||
this.store.peekAll('tag').forEach((tag) => {
|
||||
if (tag.isNew) {
|
||||
tag.destroyRecord();
|
||||
}
|
||||
});
|
||||
|
||||
// For new tags, attach the id to it, so we can link the new tag to the post
|
||||
let allTags = null;
|
||||
|
||||
for (const tag of serializedTags) {
|
||||
if (!tag.id) {
|
||||
if (!allTags) {
|
||||
// Update tags on the client side (we could have created new tags)
|
||||
yield this.store.query('tag', {limit: 'all'});
|
||||
allTags = this.store.peekAll('tag').toArray();
|
||||
}
|
||||
const createdTag = allTags.find(t => t.name === tag.name && t.id);
|
||||
if (createdTag) {
|
||||
tag.id = createdTag.id;
|
||||
tag.slug = createdTag.slug;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Update the models on the client side
|
||||
for (const post of updatedModels) {
|
||||
const newTags = post.tags.toArray().map((t) => {
|
||||
@ -117,12 +156,9 @@ export default class PostsContextMenu extends Component {
|
||||
type: 'tag'
|
||||
};
|
||||
});
|
||||
for (const tag of tags) {
|
||||
for (const tag of serializedTags) {
|
||||
if (!newTags.find(t => t.id === tag.id)) {
|
||||
newTags.push({
|
||||
...tag.serialize({includeId: true}),
|
||||
type: 'tag'
|
||||
});
|
||||
newTags.push(tag);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -22,6 +22,13 @@ export default class AddTag extends Component {
|
||||
// store and be updated when the above query returns
|
||||
this.store.query('tag', {limit: 'all'});
|
||||
this.#availableTags = this.store.peekAll('tag');
|
||||
|
||||
// Destroy unsaved new tags (otherwise we could select them again -> create them again)
|
||||
this.#availableTags.forEach((tag) => {
|
||||
if (tag.isNew) {
|
||||
tag.destroyRecord();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@action
|
||||
@ -58,11 +65,8 @@ export default class AddTag extends Component {
|
||||
}
|
||||
|
||||
@action
|
||||
shouldAllowCreate() {
|
||||
return false;
|
||||
|
||||
// This is not supported by the backend yet
|
||||
// return !this.#findTagByName(nameInput.trim(), this.#availableTags);
|
||||
shouldAllowCreate(nameInput) {
|
||||
return !this.#findTagByName(nameInput.trim(), this.#availableTags);
|
||||
}
|
||||
|
||||
#findTagByName(name, tags) {
|
||||
|
@ -8,6 +8,7 @@ const messages = {
|
||||
invalidVisibilityFilter: 'Invalid visibility filter.',
|
||||
invalidVisibility: 'Invalid visibility value.',
|
||||
invalidTiers: 'Invalid tiers value.',
|
||||
invalidTags: 'Invalid tags value.',
|
||||
invalidEmailSegment: 'The email segment parameter doesn\'t contain a valid filter',
|
||||
unsupportedBulkAction: 'Unsupported bulk action'
|
||||
};
|
||||
@ -95,6 +96,23 @@ class PostsService {
|
||||
return await this.#updatePosts({visibility: data.meta.visibility, tiers}, {filter: options.filter});
|
||||
}
|
||||
if (data.action === 'addTag') {
|
||||
if (!Array.isArray(data.meta.tags)) {
|
||||
throw new errors.IncorrectUsageError({
|
||||
message: tpl(messages.invalidTags)
|
||||
});
|
||||
}
|
||||
for (const tag of data.meta.tags) {
|
||||
if (typeof tag !== 'object') {
|
||||
throw new errors.IncorrectUsageError({
|
||||
message: tpl(messages.invalidTags)
|
||||
});
|
||||
}
|
||||
if (!tag.id && !tag.name) {
|
||||
throw new errors.IncorrectUsageError({
|
||||
message: tpl(messages.invalidTags)
|
||||
});
|
||||
}
|
||||
}
|
||||
return await this.#bulkAddTags({tags: data.meta.tags}, {filter: options.filter});
|
||||
}
|
||||
throw new errors.IncorrectUsageError({
|
||||
@ -118,17 +136,25 @@ class PostsService {
|
||||
});
|
||||
}
|
||||
|
||||
// Create tags that don't exist
|
||||
for (const tag of data.tags) {
|
||||
if (!tag.id) {
|
||||
const createdTag = await this.models.Tag.add(tag, {transacting: options.transacting});
|
||||
tag.id = createdTag.id;
|
||||
}
|
||||
}
|
||||
|
||||
const postRows = await this.models.Post.getFilteredCollectionQuery({
|
||||
filter: options.filter,
|
||||
status: 'all'
|
||||
}).select('posts.id');
|
||||
|
||||
const postTags = data.tags.reduce((pt, tagId) => {
|
||||
const postTags = data.tags.reduce((pt, tag) => {
|
||||
return pt.concat(postRows.map((post) => {
|
||||
return {
|
||||
id: (new ObjectId()).toHexString(),
|
||||
post_id: post.id,
|
||||
tag_id: tagId,
|
||||
tag_id: tag.id,
|
||||
sort_order: 0
|
||||
};
|
||||
}));
|
||||
|
Loading…
Reference in New Issue
Block a user