Skip to main content
mwyman
February 23, 2024
Solved

Using ElementProxy to get data fields for selected Jira card

  • February 23, 2024
  • 12 replies
  • 243 views

Hello Lucid Devs and community.  I'm trying to get access to the data fields attached to a LucidSpark Card that was created using your Jira data connector/integration. I spoke with you all recently and you had suggested I leverage ElementProxy, but I’m having trouble getting it to work. Would greatly appreciate any help about where I’m going wrong. If you have any example code for this scenario that would be helpful as well. 

My 'extension.ts' file (stripped down to focus on just getting data fields):

import {
EditorClient,
Menu,
MenuType,
Viewport,
CardBlockProxy,
DataProxy,
ElementProxy,
CollectionProxy,
} from "lucid-extension-sdk";

const client = new EditorClient();
const menu = new Menu(client);
const viewport = new Viewport(client);
const data = new DataProxy(client);

async function listDataFieldsForSelectedElement(elementId: string) {
const elementProxy = new ElementProxy(elementId, client);
let fieldsSet = new Set();

for (const referenceKey of elementProxy.referenceKeys.values()) {
const dataItemProxy = referenceKey.getItem();
console.log("DataItemProxy:", dataItemProxy);

if (!dataItemProxy) {
console.error("DataItemProxy not found for referenceKey:", referenceKey);
continue;
}

const collectionProxy = dataItemProxy.collection;
console.log("CollectionProxy:", collectionProxy);

// Check if the CollectionProxy object has the fields you expect
if (collectionProxy && "getFields" in collectionProxy) {
const fields = collectionProxy.getFields();
console.log("Fields in Collection:", fields);
fields.forEach((field) => fieldsSet.add(field));
} else {
console.error(
"CollectionProxy is undefined or does not have the getFields method for dataItemProxy:",
dataItemProxy
);
}
}

return Array.from(fieldsSet);
}

client.registerAction("readCardProperties", () => {
const selectedItems = viewport.getSelectedItems(true);

if (!selectedItems || selectedItems.length === 0) {
client.alert("No items are selected.");
return;
}

for (const item of selectedItems) {
if (item instanceof CardBlockProxy) {
try {
listDataFieldsForSelectedElement(item.id)
.then((refFieldsAsString) => {
const content = `Ref Fields: ${refFieldsAsString.join(", ")}`;
console.log("Content:", content);
})
.catch((error) => {
// Handle any errors that occur during the fetch
console.error("Error reading card properties:", error);
});
} catch (error) {
console.error("Error reading card properties:", error.message);
}
} else {
console.error("Selected item is not a CardBlockProxy instance.");
}
}
});

client.registerAction("itemsSelected", () => {
const items = viewport.getSelectedItems(true);
return items && items.length > 0;
});

menu.addMenuItem({
label: "Read Card Properties",
action: "readCardProperties",
menuType: MenuType.Context,
visibleAction: "itemsSelected",
});

Screen capture of browser console:

Copy of console log output when action called in case you want to see it:

EditorClient, fields: MapProxy}client: EditorClient {nextId: 0, callbacks: Map(3)}collection: CollectionProxyclient: EditorClient {nextId: 0, callbacks: Map(3)}id: "r5+QdQnqOxwpdmF4iPKubi5yo54="items: MapProxygetItem: (primaryKey) => {…}length: 1name: ""arguments: [Exception: TypeError: 'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them

    at Function.invokeGetter (<anonymous>:3:28)]caller: [Exception: TypeError: 'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them

    at Function.invokeGetter (<anonymous>:3:28)][[FunctionLocation]]: collectionproxy.js:29[[Prototype]]: ƒ ()[[Scopes]]: Scopes[7]getKeys: () => {…}size: (...)[[Prototype]]: Objectproperties: WriteableMapProxy {getKeys: ƒ, getItem: ƒ, setter: ƒ}[[Prototype]]: PropertyStoreProxyfields: MapProxy {getKeys: ƒ, getItem: ƒ}primaryKey: "\"AGTA-846\""[[Prototype]]: Object

extension.ts:39 CollectionProxy: CollectionProxy {id: 'r5+QdQnqOxwpdmF4iPKubi5yo54=', client: EditorClient, properties: WriteableMapProxy, items: MapProxy}client: EditorClient {nextId: 0, callbacks: Map(3)}id: "r5+QdQnqOxwpdmF4iPKubi5yo54="items: MapProxy {getKeys: ƒ, getItem: ƒ}properties: WriteableMapProxy {getKeys: ƒ, getItem: ƒ, setter: ƒ}[[Prototype]]: PropertyStoreProxyconstructor: class CollectionProxygetBranchedFrom: ƒ getBranchedFrom()getFields: ƒ getFields()length: 0name: "getFields"arguments: [Exception: TypeError: 'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them

    at Function.invokeGetter (<anonymous>:3:28)]caller: [Exception: TypeError: 'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them

    at Function.invokeGetter (<anonymous>:3:28)][[FunctionLocation]]: collectionproxy.js:86[[Prototype]]: ƒ ()[[Scopes]]: Scopes[7]getLocalChanges: ƒ getLocalChanges()getName: ƒ getName()getSchema: ƒ getSchema()getSyncCollectionId: ƒ getSyncCollectionId()patchItems: ƒ patchItems(patch)[[Prototype]]: Object

2c2fc614ad2208c1a1f0bcb45e551fca796817167ded9dc88b07efd38f95c5.js.br:9551 Action readCardProperties took 2.80ms

extension.ts:78  Error reading card properties: Error: Collection not found: r5+QdQnqOxwpdmF4iPKubi5yo54=

Best answer by Connor B

The fix should be released now! This should address the ‘no collection’ errors you have been seeing. Let us know if anything else comes up!

Comments

mwyman
mwymanAuthor
March 13, 2024

Hello again Connor and the rest of the Lucid team. I was able to test further and I think maybe I’ve found a related bug, although I’ll be happy if I’m mistaken. I am now able to read the field values thanks to your fix and can confirm it works well so far. However, when I try to update a field value using ‘patchItems’ on the CollectionProxy I am getting the same type of error message as before saying it “could not find collection...” 

I set up a simple demonstration in the code below for your review, with a hard-coded update value in string format. I picked a field called “summary” which is just a string to hopefully rule out type compatibility issues. Thanks again for all of your help!

Here’s my function getFieldValueFromElement, and you can see that all of the read the fields from the collection (and display the collection itself) up until I execute the patch command.

export async function getFieldValueFromElement(
client: EditorClient,
elementId: string,
fieldName: string
) {
// Obtain an ElementProxy for the given elementId
const elementProxy = new ElementProxy(elementId, client);
// Check if elementProxy is null or undefined
if (!elementProxy) {
throw new Error(`Element with ID ${elementId} not found.`);
}

// Iterate over reference keys to find the associated data item
for (const referenceKey of elementProxy.referenceKeys.values()) {
const dataItemProxy = referenceKey.getItem();
if (!dataItemProxy) {
continue; // Skip if no data item proxy is associated with this reference key
}

// Obtain the CollectionProxy from the DataItemProxy
const collectionProxy = dataItemProxy.collection;
if (collectionProxy) {
// Get all field names for the collection
const fields = collectionProxy.getFields();
console.log("Fields in Collection:", fields);
if (fields.includes(fieldName)) {
// Get the value for the specified field
const fieldValue = dataItemProxy.fields.get(fieldName);

if (fieldValue !== undefined) {
/************************************************************** */
// Test code for patch ability
// Assuming passed in field name contains a string value
/************************************************************** */

const testNewValue = "Test updated value";

console.log(`Attempting to change value of ${fieldName}`);
console.log(`Current Value of ${fieldName}:`, fieldValue);

const primaryKey = dataItemProxy.primaryKey;

console.log(`Primary Key:`, primaryKey);

const changedItems = new Map();
changedItems.set(primaryKey, { [fieldName]: testNewValue });

console.log("Changed Items Map:", changedItems);
console.log("CollectionProxy:", collectionProxy);

collectionProxy.patchItems({ changed: changedItems });

console.log(
`New Value of ${fieldName}:`,
dataItemProxy.fields.get(fieldName)
);
/************************************************************** */

return fieldValue; // Return the found value
}
}
}
}

// If the loop completes without returning, the field was not found
throw new Error(
`Field '${fieldName}' not found in any referenced data items.`
);
}

Here’s a capture of the console log:

 

Richard Udell
Lucid support team
March 18, 2024

Hi @mwyman thank you for your question. Just closing out this thread - I see that you also started a new thread and I understand you’ve received direct support from our Development team on this! Thanks for using our APIs.