1
1
mirror of https://github.com/n8n-io/n8n.git synced 2024-07-14 16:30:27 +03:00

refactor(editor): Migrate tags.store to use composition API (no-changelog) (#9891)

This commit is contained in:
Ricardo Espinoza 2024-07-02 14:15:20 -04:00 committed by GitHub
parent 873b7e59dc
commit 8debac755e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 107 additions and 98 deletions

View File

@ -30,7 +30,7 @@ const initialState = {
areTagsEnabled: true,
},
[STORES.TAGS]: {
tags: {
tagsById: {
1: {
id: '1',
name: 'tag1',

View File

@ -413,7 +413,7 @@ async function onWorkflowMenuSelect(action: WORKFLOW_MENU_ACTIONS): Promise<void
instanceId: rootStore.instanceId,
},
tags: (tags ?? []).map((tagId) => {
const { usageCount, ...tag } = tagsStore.getTagById(tagId);
const { usageCount, ...tag } = tagsStore.tagsById[tagId];
return tag;
}),

View File

@ -103,7 +103,7 @@ export default defineComponent({
},
tags() {
const tags = this.tagIds
.map((tagId: string) => this.tagsStore.getTagById(tagId))
.map((tagId: string) => this.tagsStore.tagsById[tagId])
.filter(Boolean); // if tag has been deleted from store
let toDisplay: TagEl[] = this.limit ? tags.slice(0, this.limit) : tags;

View File

@ -130,7 +130,7 @@ export default defineComponent({
});
const appliedTags = computed<string[]>(() => {
return props.modelValue.filter((id: string) => tagsStore.getTagById(id));
return props.modelValue.filter((id: string) => tagsStore.tagsById[id]);
});
watch(

View File

@ -72,7 +72,7 @@ export default defineComponent({
return this.tagsStore.isLoading;
},
tags(): ITag[] {
return this.tagIds.map((tagId: string) => this.tagsStore.getTagById(tagId)).filter(Boolean); // if tag is deleted from store
return this.tagIds.map((tagId: string) => this.tagsStore.tagsById[tagId]).filter(Boolean); // if tag is deleted from store
},
hasTags(): boolean {
return this.tags.length > 0;
@ -110,7 +110,7 @@ export default defineComponent({
},
async onUpdate(id: string, name: string, cb: (tag: boolean, error?: Error) => void) {
const tag = this.tagsStore.getTagById(id);
const tag = this.tagsStore.tagsById[id];
const oldName = tag.name;
try {
@ -144,11 +144,11 @@ export default defineComponent({
},
async onDelete(id: string, cb: (deleted: boolean, error?: Error) => void) {
const tag = this.tagsStore.getTagById(id);
const tag = this.tagsStore.tagsById[id];
const name = tag.name;
try {
const deleted = await this.tagsStore.delete(id);
const deleted = await this.tagsStore.deleteTagById(id);
if (!deleted) {
throw new Error(this.$locale.baseText('tagsManager.couldNotDeleteTag'));
}

View File

@ -1,105 +1,114 @@
import { createTag, deleteTag, getTags, updateTag } from '@/api/tags';
import * as tagsApi from '@/api/tags';
import { STORES } from '@/constants';
import type { ITag, ITagsState } from '@/Interface';
import type { ITag } from '@/Interface';
import { defineStore } from 'pinia';
import { useRootStore } from './root.store';
import { computed, ref } from 'vue';
import { useWorkflowsStore } from './workflows.store';
export const useTagsStore = defineStore(STORES.TAGS, {
state: (): ITagsState => ({
tags: {},
loading: false,
fetchedAll: false,
fetchedUsageCount: false,
}),
getters: {
allTags(): ITag[] {
return Object.values(this.tags).sort((a, b) => a.name.localeCompare(b.name));
},
isLoading(): boolean {
return this.loading;
},
hasTags(): boolean {
return Object.keys(this.tags).length > 0;
},
getTagById() {
return (id: string) => this.tags[id];
},
},
actions: {
setAllTags(tags: ITag[]): void {
this.tags = tags.reduce((accu: { [id: string]: ITag }, tag: ITag) => {
accu[tag.id] = tag;
export const useTagsStore = defineStore(STORES.TAGS, () => {
const tagsById = ref<Record<string, ITag>>({});
const loading = ref(false);
const fetchedAll = ref(false);
const fetchedUsageCount = ref(false);
return accu;
}, {});
this.fetchedAll = true;
},
upsertTags(tags: ITag[]): void {
tags.forEach((tag) => {
const tagId = tag.id;
const currentTag = this.tags[tagId];
if (currentTag) {
const newTag = {
...currentTag,
...tag,
};
this.tags = {
...this.tags,
[tagId]: newTag,
};
} else {
this.tags = {
...this.tags,
[tagId]: tag,
};
}
});
},
deleteTag(id: string): void {
const { [id]: deleted, ...rest } = this.tags;
this.tags = rest;
},
const rootStore = useRootStore();
const workflowsStore = useWorkflowsStore();
async fetchAll(params?: { force?: boolean; withUsageCount?: boolean }): Promise<ITag[]> {
const { force = false, withUsageCount = false } = params || {};
if (!force && this.fetchedAll && this.fetchedUsageCount === withUsageCount) {
return Object.values(this.tags);
// Computed
const allTags = computed(() => {
return Object.values(tagsById.value).sort((a, b) => a.name.localeCompare(b.name));
});
const isLoading = computed(() => loading.value);
const hasTags = computed(() => Object.keys(tagsById.value).length > 0);
// Methods
const setAllTags = (loadedTags: ITag[]) => {
tagsById.value = loadedTags.reduce((accu: { [id: string]: ITag }, tag: ITag) => {
accu[tag.id] = tag;
return accu;
}, {});
fetchedAll.value = true;
};
const upsertTags = (toUpsertTags: ITag[]) => {
toUpsertTags.forEach((toUpsertTag) => {
const tagId = toUpsertTag.id;
const currentTag = tagsById.value[tagId];
if (currentTag) {
const newTag = {
...currentTag,
...toUpsertTag,
};
tagsById.value = {
...tagsById.value,
[tagId]: newTag,
};
} else {
tagsById.value = {
...tagsById.value,
[tagId]: toUpsertTag,
};
}
});
};
this.loading = true;
const rootStore = useRootStore();
const tags = await getTags(rootStore.restApiContext, Boolean(withUsageCount));
this.setAllTags(tags);
this.loading = false;
const deleteTag = (id: string) => {
const { [id]: deleted, ...rest } = tagsById.value;
tagsById.value = rest;
};
return tags;
},
async create(name: string): Promise<ITag> {
const rootStore = useRootStore();
const tag = await createTag(rootStore.restApiContext, { name });
this.upsertTags([tag]);
const fetchAll = async (params?: { force?: boolean; withUsageCount?: boolean }) => {
const { force = false, withUsageCount = false } = params || {};
if (!force && fetchedAll.value && fetchedUsageCount.value === withUsageCount) {
return Object.values(tagsById.value);
}
return tag;
},
async rename({ id, name }: { id: string; name: string }) {
const rootStore = useRootStore();
const tag = await updateTag(rootStore.restApiContext, id, { name });
this.upsertTags([tag]);
loading.value = true;
const retrievedTags = await tagsApi.getTags(rootStore.restApiContext, Boolean(withUsageCount));
setAllTags(retrievedTags);
loading.value = false;
return retrievedTags;
};
return tag;
},
async delete(id: string) {
const rootStore = useRootStore();
const deleted = await deleteTag(rootStore.restApiContext, id);
const create = async (name: string) => {
const createdTag = await tagsApi.createTag(rootStore.restApiContext, { name });
upsertTags([createdTag]);
return createdTag;
};
if (deleted) {
this.deleteTag(id);
const workflowsStore = useWorkflowsStore();
workflowsStore.removeWorkflowTagId(id);
}
const rename = async ({ id, name }: { id: string; name: string }) => {
const updatedTag = await tagsApi.updateTag(rootStore.restApiContext, id, { name });
upsertTags([updatedTag]);
return updatedTag;
};
return deleted;
},
},
const deleteTagById = async (id: string) => {
const deleted = await tagsApi.deleteTag(rootStore.restApiContext, id);
if (deleted) {
deleteTag(id);
workflowsStore.removeWorkflowTagId(id);
}
return deleted;
};
return {
allTags,
isLoading,
hasTags,
tagsById,
fetchAll,
create,
rename,
deleteTagById,
upsertTags,
deleteTag,
};
});