Skip to content

Commit

Permalink
feat: Add method to Card instances for fetching associated Custom Fie…
Browse files Browse the repository at this point in the history
…ld definitions.
  • Loading branch information
adam-coster committed Aug 21, 2021
1 parent 16eed35 commit 24a3087
Show file tree
Hide file tree
Showing 2 changed files with 102 additions and 11 deletions.
29 changes: 29 additions & 0 deletions src/lib/clientLib/BravoResponse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,13 @@ export class BravoResponseEntities<
private _entitiesCache: Entity[] = [];
private _hydratedLatestPage = false;
private _latestPage?: FavroResponse<EntityData>;
/**
* Entities to cache in a *map* while looping over entries,
* but with multiple caches (one for each identifier field).
*/
private _entitiesCachedById: {
[identifierField: string]: { [id: string]: Entity };
} = {};

constructor(
private _client: BravoClient,
Expand Down Expand Up @@ -87,6 +94,28 @@ export class BravoResponseEntities<
}
}

/**
* Find an entity by an identifier field.
*/
async findById(identifierName: string, identifierValue: string) {
// Ensure we have the per-identifier name cache
this._entitiesCachedById[identifierName] ||= {};
const cache = this._entitiesCachedById[identifierName];
const entity = cache[identifierValue];
if (entity) {
return entity;
}

// Need to iterate over the list! But we can cache as we go.
for await (const entity of this) {
cache[identifierValue] ||= entity;
// @ts-expect-error
if (entity[identifierName] === identifierValue) {
return entity;
}
}
}

/**
* Exhaustively fetch all entities (including those on
* subsequent pages, requiring additional API calls),
Expand Down
84 changes: 73 additions & 11 deletions src/lib/entities/BravoCard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
wrapIfNotArray,
} from '../utility.js';
import type { BravoColumn } from './BravoColumn.js';
import { BravoCustomFieldDefinition } from './BravoCustomField.js';

/**
* A Card update can be pretty complex, and to save API
Expand Down Expand Up @@ -237,17 +238,6 @@ export class BravoCardInstance extends BravoEntity<DataFavroCard> {
return this._data.cardCommonId;
}

/**
* The column this card appears in (i.e. the status it has)
* on the current widget. */
get columnId() {
return this._data.columnId;
}

get parentCardId() {
return this._data.parentCardId;
}

/**
* The widget that the current instance of this
* card appears in. (A single card can live in,
Expand All @@ -257,6 +247,9 @@ export class BravoCardInstance extends BravoEntity<DataFavroCard> {
return this._data.widgetCommonId;
}

/**
* The list of tag IDs associated with this card.
*/
get tags() {
return [...this._data.tags];
}
Expand All @@ -265,6 +258,30 @@ export class BravoCardInstance extends BravoEntity<DataFavroCard> {
return this._data.detailedDescription;
}

/**
* The column this card appears in (i.e. the status it has)
* on the current widget. */
get columnId() {
return this._data.columnId;
}

/**
* Get the raw Custom Field IDs and values associated
* with this card. (These are global, not per-Widget.)
*
* These are typically a collection of IDs and values.
* For more human-friendly versions, with hydrated classes
* populating all of the info,
* see {@link BravoCardInstance.getCustomFields}.
*/
get customFieldsValuesRaw() {
return [...this._data.customFields];
}

get parentCardId() {
return this._data.parentCardId;
}

get attachments() {
return this._data.attachments;
}
Expand Down Expand Up @@ -297,6 +314,51 @@ export class BravoCardInstance extends BravoEntity<DataFavroCard> {
return this._updateBuilder;
}

/**
* Get the custom field definitions associated with
* the custom field values that are set on this card.
*
* Note that definitions are only discoverable for *set*
* custom field values on the card, even though in the Favro UI you
* can see others that are not set.
*/
async getCustomFieldDefinitions() {
const cardFieldValueMap: {
[customFieldId: string]: BravoCustomFieldDefinition;
} = {};
const definitions = await this._client.listCustomFieldDefinitions();
for (const value of this.customFieldsValuesRaw) {
const definition = await definitions.findById(
'customFieldId',
value.customFieldId,
);
assertBravoClaim(
definition,
`Could not find Custom Field with ID ${value.customFieldId}`,
);
cardFieldValueMap[value.customFieldId] = definition;
}
return cardFieldValueMap;
}

// /**
// * Get full information about the populated custom fields
// * on this Card.
// */
// async getCustomFieldsValues() {
// const definitions = await this.getCustomFieldDefinitions();
// const values: BravoCustomFieldValue[] = [];
// for (const rawValue of this.customFieldsValuesRaw) {
// values.push(
// new BravoCustomFieldValue(
// rawValue,
// definitions[rawValue.customFieldId],
// ),
// );
// }
// return values;
// }

/**
* Get the list of Columns (statuses) that this Card Instance
* could be assigned to on its current Widget.
Expand Down

0 comments on commit 24a3087

Please sign in to comment.