cheetah-framework
Version:
Cheetah Framework JS used in all our applications
137 lines (110 loc) • 3.32 kB
JavaScript
const defaultParserOptions = {
verb: 'index',
acceptedFieldFilter: () => true,
afterFieldParse: field => field,
labelPrefix: 'structure.labels.'
}
class Structure {
constructor (structure, parserOptions = {}) {
this.parserOptions = _.defaults(parserOptions, defaultParserOptions)
this.structure = structure[this.parserOptions.verb]
this.translationErrors = []
this.warn = true
}
toQueryBuilderFields () {
this.translationErrors.splice(0)
const fields = this.parseFieldStructure(this.convertToFieldMap())
if (this.warn && this.translationErrors.length) {
console.warn(this.translationErrors.join(',\n'))
}
return fields
}
noWarn () {
this.warn = false
return this
}
convertToFieldMap () {
const fieldMap = new Map()
_.each(this.structure.criteria_fields, fieldData => {
if (
!this.parserOptions.acceptedFieldFilter(fieldData) || // If field is not accepted by user-defined filter
!this.isAcceptedField(fieldData) // or by default filter.
) {
return
}
const keyPath = fieldData.field.split('.')
const fieldKey = keyPath.pop()
this.buildFieldStructure(keyPath, fieldKey, fieldData, fieldMap)
})
return fieldMap
}
isAcceptedField (field) {
if (field.type === 'array' && _.get(field, 'sub_definition.length') !== 1) {
return false
}
return true
}
buildFieldStructure (keyPath, fieldKey, field, fieldMap, relationPath = []) {
if (keyPath.length) {
if (this.keyIsRelation([...relationPath, keyPath[0]].join('.'))) {
const subKey = keyPath.shift()
if (!fieldMap.has(subKey)) {
fieldMap.set(subKey, new Map())
}
this.buildFieldStructure(keyPath, fieldKey, field, fieldMap.get(subKey), [...relationPath, subKey])
} else {
fieldMap.set([...keyPath, fieldKey].join('.'), field)
}
} else {
fieldMap.set(fieldKey, field)
}
}
parseFieldStructure (fieldMap) {
return _.map([...fieldMap], ([fieldKey, field]) => {
const parsedField = this.parseField(field, fieldKey)
return this.parserOptions.afterFieldParse(parsedField)
})
}
parseField (field, key) {
const baseField = {
key,
label: key.split('.').map(key => {
const path = this.parserOptions.labelPrefix + key
if (cheetahApp.$te(path)) {
return cheetahApp.$tc(path)
} else {
this.translationErrors.push(`Missing translation path "${path}"`)
}
return path
}).join(' → ')
}
if (field instanceof Map) {
return {
...baseField,
type: 'relation',
relationFields: this.parseFieldStructure(field)
}
}
if (field.type === 'array') {
return this.parseField(_.head(field.sub_definition), key)
}
if (field.enum_values) {
return {
...baseField,
type: 'enum',
choices: field.enum_values
}
}
const [type, typeModifier] = field.type.split(':')
return {
...baseField,
type,
typeModifier,
...(field.type === 'model' ? { resource: field.related } : {})
}
}
keyIsRelation (key) {
return _.includes(this.structure.with, key)
}
}
export default Structure