diff --git a/packages/sdk/src/controllers/SubscriberController.ts b/packages/sdk/src/controllers/SubscriberController.ts index b59f4e32..71936636 100644 --- a/packages/sdk/src/controllers/SubscriberController.ts +++ b/packages/sdk/src/controllers/SubscriberController.ts @@ -1,5 +1,6 @@ import { ConfigType, Id } from '../types/CommonTypes'; import { MeasurementUnit } from '../types/LayoutTypes'; +import { ListVariable, ListVariableItem, Variable, VariableType } from '../types/VariableTypes'; import { ViewMode } from '../types/ViewModeTypes'; import { ToolType } from '../utils/enums'; @@ -143,7 +144,27 @@ export class SubscriberController { */ onVariableListChanged = (variablesJson: string) => { const callBack = this.config.onVariableListChanged; - callBack && callBack(JSON.parse(variablesJson)); + + // TODO: Revert in part 2. + if (!callBack) { + return; + } + + const parsed = JSON.parse(variablesJson) as Variable[]; + + const updated = parsed.map((variable) => + variable.type === VariableType.list + ? { + ...variable, + items: ((variable as ListVariable).items as unknown as ListVariableItem[]).map( + (item) => item.value, + ), + selected: ((variable as ListVariable).selected as unknown as ListVariableItem | undefined)?.value, + } + : variable, + ); + + callBack(updated); }; /** diff --git a/packages/sdk/src/controllers/VariableController.ts b/packages/sdk/src/controllers/VariableController.ts index c6cd6a63..7581aa0d 100644 --- a/packages/sdk/src/controllers/VariableController.ts +++ b/packages/sdk/src/controllers/VariableController.ts @@ -1,6 +1,6 @@ import { EditorAPI, Id } from '../types/CommonTypes'; import { ConnectorRegistration } from '../types/ConnectorTypes'; -import { Variable, VariableType } from '../types/VariableTypes'; +import { ListVariable, ListVariableItem, Variable, VariableType } from '../types/VariableTypes'; import { getEditorResponseData } from '../utils/EditorResponseData'; /** @@ -26,7 +26,16 @@ export class VariableController { */ getAll = async () => { const res = await this.#editorAPI; - return res.getVariables().then((result) => getEditorResponseData(result)); + return res + .getVariables() + .then((result) => getEditorResponseData(result)) + .then((resp) => { + const update = resp; + if (update.parsedData) { + update.parsedData = this.makeVariablesBackwardsCompatible(update.parsedData); + } + return update; + }); }; /** @@ -36,7 +45,16 @@ export class VariableController { */ getById = async (id: string) => { const res = await this.#editorAPI; - return res.getVariableById(id).then((result) => getEditorResponseData(result)); + return res + .getVariableById(id) + .then((result) => getEditorResponseData(result)) + .then((resp) => { + const update = resp; + if (update.parsedData) { + update.parsedData = this.makeVariableBackwardsCompatible(update.parsedData); + } + return update; + }); }; /** @@ -46,7 +64,16 @@ export class VariableController { */ getByName = async (name: string) => { const res = await this.#editorAPI; - return res.getVariableByName(name).then((result) => getEditorResponseData(result)); + return res + .getVariableByName(name) + .then((result) => getEditorResponseData(result)) + .then((resp) => { + const update = resp; + if (update.parsedData) { + update.parsedData = this.makeVariableBackwardsCompatible(update.parsedData); + } + return update; + }); }; /** @@ -116,7 +143,12 @@ export class VariableController { */ setListVariable = async (id: Id, items: string[]) => { const res = await this.#editorAPI; - return res.setListVariableItems(id, items).then((result) => getEditorResponseData(result)); + return res + .setListVariableItems( + id, + items.map((item) => JSON.stringify({ value: item })), + ) + .then((result) => getEditorResponseData(result)); }; /** @@ -257,4 +289,32 @@ export class VariableController { removeSource = async (id: string) => { return this.setValue(id, null); }; + + private makeVariablesBackwardsCompatible(variables: Variable[]) { + return variables.map((variable) => { + return this.makeVariableBackwardsCompatible(variable); + }); + } + + private makeVariableBackwardsCompatible(variable: Variable) { + if (variable.type !== VariableType.list) { + return variable; + } + + return this.makeListVariableBackwardsCompatible(variable as ListVariable); + } + + private makeListVariableBackwardsCompatible(listVariable: ListVariable) { + const updated = listVariable; + + const items = listVariable.items as unknown as ListVariableItem[]; + const selected = listVariable.selected as unknown as ListVariableItem | undefined; + + const newItems = items.map((item) => item.value); + + updated.items = newItems; + updated.selected = selected?.value; + + return updated; + } } diff --git a/packages/sdk/src/index.ts b/packages/sdk/src/index.ts index 35a014db..b472dd17 100644 --- a/packages/sdk/src/index.ts +++ b/packages/sdk/src/index.ts @@ -49,6 +49,7 @@ export type { LongTextVariable, ShortTextVariable, ListVariable, + ListVariableItem, BooleanVariable, ConnectorImageVariableSource, } from './types/VariableTypes'; diff --git a/packages/sdk/src/tests/controllers/SubscriberContoller.test.ts b/packages/sdk/src/tests/controllers/SubscriberContoller.test.ts index 5aacdceb..a9330857 100644 --- a/packages/sdk/src/tests/controllers/SubscriberContoller.test.ts +++ b/packages/sdk/src/tests/controllers/SubscriberContoller.test.ts @@ -164,9 +164,14 @@ describe('SubscriberController', () => { expect(mockEditorApi.onDocumentLoaded).toHaveBeenCalledTimes(1); }); it('Should be possible to subscribe to onVariableListChanged', async () => { - await mockedSubscriberController.onVariableListChanged('[{"id":"1","type":"group"}]'); + await mockedSubscriberController.onVariableListChanged( + '[{"id":"1","type":"group"},{"id":"varList","type":"list","selected": {"value": "Orange"},"items":[{"value":"Apple"},{"value":"Pear"},{"value":"Orange"}]}]', + ); expect(mockEditorApi.onVariableListChanged).toHaveBeenCalled(); - expect(mockEditorApi.onVariableListChanged).toHaveBeenCalledWith([{ id: '1', type: VariableType.group }]); + expect(mockEditorApi.onVariableListChanged).toHaveBeenCalledWith([ + { id: '1', type: VariableType.group }, + { id: 'varList', type: VariableType.list, selected: 'Orange', items: ['Apple', 'Pear', 'Orange'] }, + ]); }); it('Should be possible to subscribe to onSelectedLayoutFramesChanged', async () => { await mockedSubscriberController.onSelectedLayoutFramesChanged('5'); diff --git a/packages/sdk/src/tests/controllers/VariableController.test.ts b/packages/sdk/src/tests/controllers/VariableController.test.ts index 8f0c3c74..02f82801 100644 --- a/packages/sdk/src/tests/controllers/VariableController.test.ts +++ b/packages/sdk/src/tests/controllers/VariableController.test.ts @@ -1,5 +1,5 @@ import { VariableController } from '../../controllers/VariableController'; -import { ImageVariable, VariableType } from '../../types/VariableTypes'; +import { ImageVariable, ListVariable, ListVariableItem, Variable, VariableType } from '../../types/VariableTypes'; import { EditorAPI } from '../../types/CommonTypes'; import { getEditorResponseData, castToEditorResponse } from '../../utils/EditorResponseData'; import { ConnectorRegistration, ConnectorRegistrationSource } from '../../types/ConnectorTypes'; @@ -32,10 +32,25 @@ describe('VariableController', () => { }, }; + const listVar: Variable & { items: ListVariableItem[]; selected?: ListVariableItem } = { + id: variableId, + type: VariableType.list, + name: '', + label: '', + isVisible: true, + isReadonly: false, + isRequired: false, + occurrences: 0, + selected: { value: 'abc', displayValue: 'A-B-C' }, + items: [{ value: 'abc', displayValue: 'A-B-C' }], + }; + + const variables = [listVar]; + const mockEditorApi: EditorAPI = { getVariableById: async () => getEditorResponseData(castToEditorResponse(variable)), - getVariableByName: async () => getEditorResponseData(castToEditorResponse(null)), - getVariables: async () => getEditorResponseData(castToEditorResponse(null)), + getVariableByName: async () => getEditorResponseData(castToEditorResponse(listVar)), + getVariables: async () => getEditorResponseData(castToEditorResponse(variables)), addVariable: async () => getEditorResponseData(castToEditorResponse(null)), removeVariables: async () => getEditorResponseData(castToEditorResponse(null)), setVariableLabel: async () => getEditorResponseData(castToEditorResponse(null)), @@ -88,14 +103,20 @@ describe('VariableController', () => { }); it('get variable by name', async () => { - await mockedVariableController.getByName('name'); + const result = await mockedVariableController.getByName('name'); expect(mockEditorApi.getVariableByName).toHaveBeenCalledTimes(1); expect(mockEditorApi.getVariableByName).toHaveBeenCalledWith('name'); + // Backwards compatibility layer maps the new `VariableListItem` into a string. + expect((result.parsedData as ListVariable).items).toStrictEqual(['abc']); + expect((result.parsedData as ListVariable).selected).toStrictEqual('abc'); }); it('get variable list', async () => { - await mockedVariableController.getAll(); + const result = await mockedVariableController.getAll(); expect(mockEditorApi.getVariables).toHaveBeenCalledTimes(1); + // Backwards compatibility layer maps the new `VariableListItem` into a string. + expect((result.parsedData as ListVariable[])[0].items).toStrictEqual(['abc']); + expect((result.parsedData as ListVariable[])[0].selected).toStrictEqual('abc'); }); it('create a new variable', async () => { @@ -131,7 +152,10 @@ describe('VariableController', () => { it('sets the variable list items', async () => { await mockedVariableController.setListVariable('listId', ['a', 'b', 'c']); expect(mockEditorApi.setListVariableItems).toHaveBeenCalledTimes(1); - expect(mockEditorApi.setListVariableItems).toHaveBeenCalledWith('listId', ['a', 'b', 'c']); + expect(mockEditorApi.setListVariableItems).toHaveBeenCalledWith( + 'listId', + ([{ value: 'a' }, { value: 'b' }, { value: 'c' }]).map((item) => JSON.stringify(item)), + ); }); it('set variable string value', async () => { diff --git a/packages/sdk/src/types/VariableTypes.ts b/packages/sdk/src/types/VariableTypes.ts index db23f97c..f4cf162e 100644 --- a/packages/sdk/src/types/VariableTypes.ts +++ b/packages/sdk/src/types/VariableTypes.ts @@ -47,6 +47,11 @@ export interface ImageVariable extends Variable { value?: ConnectorImageVariableSource; } +export interface ListVariableItem { + value: string; + displayValue?: string; +} + export interface ListVariable extends Variable { items: string[]; selected?: string;