ember-frost-bunsen
Version:
Create UI's from JSON configurations.
179 lines (153 loc) • 5.92 kB
JavaScript
/**
* Utilitiy functions for working with lists, mainly used by select renderer
*/
import {utils} from 'bunsen-core'
import Ember from 'ember'
const {Logger, RSVP, get, typeOf} = Ember
const {isArray} = Array
/**
* set a list's available options
* @param {String} bunsenId - the bunsen id for this property
* @param {Object[]} data - initializes the list with this
* @param {String} filter - the optional string to filter on
* @param {Object} options - the bunsen model definition
* @param {Object} store - the ember-data store
* @param {Object} value - the current value object for the form instance
* @returns {RSVP.Promise} a promise that resolves to a list of items
*/
export function getOptions ({ajax, bunsenId, data, filter = '', options, store, value}) {
const filterRegex = new RegExp(filter, 'i')
const filteredData = data.filter((item) => filterRegex.test(item.label))
if (options.modelType) {
return getItemsFromEmberData(value, options, filteredData, bunsenId, store, filter)
} else if (options.endpoint) {
return getItemsFromAjaxCall({ajax, bunsenId, data: filteredData, filter, options, value})
}
return RSVP.resolve(filteredData)
}
/**
* Get query with property references replaced by property values.
* @param {String} bunsenId - bunsen ID of property (used for relative references)
* @param {String} filter - the partial match query filter to populate
* @param {Object} query - query to process references in
* @param {Object} value - the bunsen value for this form
* @returns {Object} query object with references filled in
*/
export function getQuery ({bunsenId, filter, query, value}) {
const result = utils.populateQuery(value, query, bunsenId)
if (typeOf(result) !== 'object') {
return result
}
// replace the special $filter placeholder with the filter value (if it exists)
Object.keys(result).forEach((key) => {
const value = result[key]
if (typeOf(value) === 'string') {
result[key] = value.replace('$filter', filter)
}
})
return result
}
/**
* take enum values and make into a collection
* @param {String[]} values the values to make into a collection
* @param {String} filter - filter
* @returns {Object[]} a list of item objects
*/
export function getEnumValues (values = [], filter = '') {
const filteredValues = []
values.filter((value) => {
if (!filter || value.toLowerCase().indexOf(filter.toLowerCase()) !== -1) {
filteredValues.push({label: value, value})
}
})
return filteredValues
}
/**
* Fetch the list of items from an API endpoint
* @param {Object} ajax - ember-ajax service
* @param {Object} bunsenId - the bunsenId for this form
* @param {Object[]} data - initializes the list with this
* @param {String} filter - the partial match query filter to populate
* @param {Object} options - bunsen model for this property plus view renderer options
* @param {Object} value - the bunsen value for this form
* @returns {RSVP.Promise} a promise that resolves with the list of items
*/
export function getItemsFromAjaxCall ({ajax, bunsenId, data, filter, options, value}) {
const query = getQuery({
bunsenId,
filter,
query: options.query,
value
})
const queryString = Object.keys(query)
.map((key) => `${key}=${query[key]}`)
.join('&')
const url = queryString ? `${options.endpoint}?${queryString}` : options.endpoint
return ajax.request(url)
.then((result) => {
const records = options.recordsPath ? get(result, options.recordsPath) : result
if (!isArray(records)) {
Logger.warn(
`Expected an array of records at "${options.recordPath}" but got:`,
records
)
return []
}
const {labelAttribute, valueAttribute} = options
return normalizeItems({data, labelAttribute, records, valueAttribute})
})
.catch((err) => {
Logger.error(`Error fetching endpoint "${options.endpoint}"`, err)
throw err
})
}
/**
* Fetch the list of network functions from the backend and set them
* @param {Object} value the bunsen value for this form
* @param {Object} modelDef the full bunsen model def for this property
* @param {Object[]} data initializes the list with this
* @param {Object} bunsenId the bunsenId for this form
* @param {Object} store the ember-data store
* @param {String} filter the partial match query filter to populate
* @returns {RSVP.Promise} a promise that resolves to the list of items
*/
export function getItemsFromEmberData (value, modelDef, data, bunsenId, store, filter) {
const modelType = modelDef.modelType || 'resources'
const {labelAttribute, valueAttribute} = modelDef
const query = getQuery({
bunsenId,
filter,
query: modelDef.query,
value
})
return store.query(modelType, query)
.then((records) => {
return normalizeItems({data, labelAttribute, records, valueAttribute})
}).catch((err) => {
Logger.log(`Error fetching ${modelType}`, err)
throw err
})
}
/**
* Converts records from an API response into a standard format with "label"
* and "value" properties so renderers can predictably process the data.
* @param {Object[]} data - initializes the list with this
* @param {String} labelAttribute - dot notated path to label attribute in record
* @param {Array<Object>} records - records to normalize
* @param {String} valueAttribute - dot notated path to value attribute in record
* @returns {Array<Object>} normalized items
*/
function normalizeItems ({data, labelAttribute, records, valueAttribute}) {
const labelAttr = labelAttribute || 'label'
const valueAttr = valueAttribute || 'id'
return data.concat(
records.map((record) => {
const label = get(record, labelAttr) || record.get('title')
const value = get(record, valueAttr)
return {
label,
value
}
})
)
}