From be0a92af71daf97662f66a5954e17c083ae97aa1 Mon Sep 17 00:00:00 2001 From: Jiri Lojda Date: Fri, 10 Mar 2023 13:00:42 +0100 Subject: [PATCH 1/2] Provide options for taxonomy elements (terms) - it cannot be a dynamic dropdown, because there is no way to pass the dropdown info about the element it needs to fill => no way to know the taxonomy group to fetch --- package.json | 2 +- src/fields/elements/getItemElementFields.ts | 116 ++++++++++++-------- src/searches/findLanguage.ts | 1 + src/utils/range.ts | 2 +- src/utils/taxonomies/getTaxonomyGroup.ts | 10 ++ 5 files changed, 86 insertions(+), 45 deletions(-) create mode 100644 src/utils/taxonomies/getTaxonomyGroup.ts diff --git a/package.json b/package.json index 7a96d62..e2e3444 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "zapier-cli", - "version": "0.2.2", + "version": "0.2.3", "scripts": { "test": "jest", "build": "tsc", diff --git a/src/fields/elements/getItemElementFields.ts b/src/fields/elements/getItemElementFields.ts index 922427c..4f542d2 100644 --- a/src/fields/elements/getItemElementFields.ts +++ b/src/fields/elements/getItemElementFields.ts @@ -1,59 +1,89 @@ import { ZObject } from 'zapier-platform-core'; import { KontentBundle } from '../../types/kontentBundle'; import { getContentTypeElements } from './getContentTypeElements'; -import { ContentTypeElements } from '@kontent-ai/management-sdk'; +import { ContentTypeElements, TaxonomyModels } from '@kontent-ai/management-sdk'; import { Field } from '../field'; +import { getTaxonomyGroup } from '../../utils/taxonomies/getTaxonomyGroup'; -export const getItemElementFields = async (z: ZObject, bundle: KontentBundle<{}>, contentTypeId: string) => +export const getItemElementFields = (z: ZObject, bundle: KontentBundle<{}>, contentTypeId: string) => getContentTypeElements(z, bundle, contentTypeId) - .then(elements => elements.map(getSimpleElementField)); + .then(async elements => [elements, await getTermsForTaxonomyElements(z, bundle)(elements)] as const) + .then(([elements, termsByElementId]) => elements.map(getSimpleElementField(termsByElementId))); + +const getTermsForTaxonomyElements = (z: ZObject, bundle: KontentBundle<{}>) => + (elements: readonly ContentTypeElements.ContentTypeElementModel[]) => + Promise.all(elements + .filter(el => el.type === "taxonomy") + .map(async el => [el.id, await getTaxonomyGroup(z, bundle)((el as ContentTypeElements.ITaxonomyElement).taxonomy_group.id || '')] as const)) + .then(entries => entries.map(([elId, group]) => [elId, group.terms.flatMap(createTermData)] as const)) + .then(entries => new Map(entries)); + +type TermData = Readonly<{ + id: string; + name: string; +}>; + +const createTermData = (term: TaxonomyModels.Taxonomy): ReadonlyArray => [ + { + id: term.id, + name: term.name, + }, + ...term.terms.flatMap(createTermData), +]; export type ElementFields = Readonly<{ [key: `elements__${string}`]: string | string[] | number | undefined; }>; -function getSimpleElementField(element: ContentTypeElements.ContentTypeElementModel) { - switch (element.type) { - case 'text': - case 'rich_text': - case 'custom': - return getField(element, { type: 'text' }); - - case 'number': - return getField(element, { type: 'float' }); - - case 'date_time': - return getField(element, { type: 'datetime' }); - - case 'modular_content': - const opts = { - search: 'find_item.id', - list: true, - dynamic: 'get_linked_items.id.name', - type: 'string', - altersDynamicFields: false, - } as const; - - return getField(element, opts); - - case 'multiple_choice': { - const choices = element.options.map(o => ({ label: o.name, value: o.codename || '', sample: '' })); - - return getField(element, { type: 'unicode', list: element.mode === 'multiple', choices }); +const getSimpleElementField = (termsByElementId: ReadonlyMap) => + (element: ContentTypeElements.ContentTypeElementModel) => { + switch (element.type) { + case 'text': + case 'rich_text': + case 'custom': + return getField(element, { type: 'text' }); + + case 'number': + return getField(element, { type: 'float' }); + + case 'date_time': + return getField(element, { type: 'datetime' }); + + case 'modular_content': + const opts = { + search: 'find_item.id', + list: true, + dynamic: 'get_linked_items.id.name', + type: 'string', + altersDynamicFields: false, + } as const; + + return getField(element, opts); + + case 'multiple_choice': { + const choices = element.options.map(o => ({ label: o.name, value: o.codename || '', sample: '' })); + + return getField(element, { type: 'unicode', list: element.mode === 'multiple', choices }); + } + case 'asset': + return getField(element, { type: 'unicode', list: true }); + + case 'taxonomy': { + const choices = (termsByElementId.get(element.id) ?? []) + .map(t => ({ value: t.id, label: t.name, sample: t.id })); + + return getField(element, { type: 'unicode', choices, list: true }); + } + + case 'url_slug': + return getField(element, { type: 'unicode' }); + + case 'guidelines': + return getField(element, { type: 'copy' }); + default: + return undefined; } - case 'asset': - case 'taxonomy': - return getField(element, { type: 'unicode', list: true }); - - case 'url_slug': - return getField(element, { type: 'unicode' }); - - case 'guidelines': - return getField(element, { type: 'copy' }); - default: - return undefined; } -} function getField(element: ElementWithoutSnippets, extra?: Partial) { const base = { diff --git a/src/searches/findLanguage.ts b/src/searches/findLanguage.ts index 675c9c9..82e4c0b 100644 --- a/src/searches/findLanguage.ts +++ b/src/searches/findLanguage.ts @@ -80,6 +80,7 @@ export const findLanguage = { key: 'find_language', operation: { perform: execute, + outputFields, inputFields: [ ...languageSearchFields, ], diff --git a/src/utils/range.ts b/src/utils/range.ts index f8dc5cc..a4a0b69 100644 --- a/src/utils/range.ts +++ b/src/utils/range.ts @@ -1,3 +1,3 @@ export const range = (countOrStart: number, end?: number, step: number = 1) => - [...new Array((end !== undefined ? Math.floor((end - countOrStart) / step) : countOrStart))] + [...new Array(end !== undefined ? Math.floor((end - countOrStart) / step) : countOrStart)] .map((_, i) => i * step); diff --git a/src/utils/taxonomies/getTaxonomyGroup.ts b/src/utils/taxonomies/getTaxonomyGroup.ts new file mode 100644 index 0000000..c3410ad --- /dev/null +++ b/src/utils/taxonomies/getTaxonomyGroup.ts @@ -0,0 +1,10 @@ +import { ZObject } from "zapier-platform-core"; +import { KontentBundle } from "../../types/kontentBundle"; +import { createManagementClient } from "../kontentServices/managementClient"; + +export const getTaxonomyGroup = (z: ZObject, bundle: KontentBundle<{}>) => (groupId: string) => + createManagementClient(z, bundle) + .getTaxonomy() + .byTaxonomyId(groupId) + .toPromise() + .then(res => res.data); From 9b1d34a0617db0559a86b18aa5116393e67b42a3 Mon Sep 17 00:00:00 2001 From: Jiri Lojda Date: Fri, 10 Mar 2023 15:25:44 +0100 Subject: [PATCH 2/2] Add term codenames as options along with term ids --- src/fields/elements/getItemElementFields.ts | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/fields/elements/getItemElementFields.ts b/src/fields/elements/getItemElementFields.ts index 4f542d2..df523d8 100644 --- a/src/fields/elements/getItemElementFields.ts +++ b/src/fields/elements/getItemElementFields.ts @@ -21,12 +21,14 @@ const getTermsForTaxonomyElements = (z: ZObject, bundle: KontentBundle<{}>) => type TermData = Readonly<{ id: string; name: string; + codename: string; }>; const createTermData = (term: TaxonomyModels.Taxonomy): ReadonlyArray => [ { id: term.id, name: term.name, + codename: term.codename, }, ...term.terms.flatMap(createTermData), ]; @@ -69,10 +71,11 @@ const getSimpleElementField = (termsByElementId: ReadonlyMap ({ value: t.id, label: t.name, sample: t.id })); + const terms = termsByElementId.get(element.id) ?? []; + const idChoices = terms.map(t => ({ value: t.id, label: t.name, sample: t.id })); + const codenameChoices = terms.map(t => ({ value: t.codename, label: `${t.name} (codename)`, sample: t.codename })); - return getField(element, { type: 'unicode', choices, list: true }); + return getField(element, { type: 'unicode', choices: [...idChoices, ...codenameChoices], list: true }); } case 'url_slug':