chain supermarket create/update to include categories

This commit is contained in:
smilerz 2021-09-27 17:55:58 -05:00
parent 1d983d7310
commit c1a22ea2a6
14 changed files with 101 additions and 62 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -237,6 +237,7 @@ export default {
case this.Actions.UPDATE: case this.Actions.UPDATE:
update = e.form_data update = e.form_data
update.id = this.this_item.id update.id = this.this_item.id
console.log('form', update)
this.saveThis(update) this.saveThis(update)
break; break;
case this.Actions.MERGE: case this.Actions.MERGE:
@ -285,11 +286,7 @@ export default {
}) })
} else { } else {
this.genericAPI(this.this_model, this.Actions.UPDATE, thisItem).then((result) => { this.genericAPI(this.this_model, this.Actions.UPDATE, thisItem).then((result) => {
// using form data to refresh the card this.refreshThis(thisItem.id)
// when there are complicated functions (SuperMarket Relations) the actions don't
// always complete first. TODO: wrap all that in a Promise and wait for it to complete before using refreshThis instead
this.refreshCard(thisItem, this.items_left)
this.refreshCard({...thisItem}, this.items_right)
StandardToasts.makeStandardToast(StandardToasts.SUCCESS_UPDATE) StandardToasts.makeStandardToast(StandardToasts.SUCCESS_UPDATE)
}).catch((err) => { }).catch((err) => {
console.log(err, err.response) console.log(err, err.response)

View File

@ -284,9 +284,14 @@ export class Models {
}, },
}, },
'config': { 'config': {
'category_to_supermarket': {'function': 'handleSuperMarketCategory'} 'function': 'SupermarketWithCategories',
} }
}, },
'partialUpdate': {
'config': {
'function': 'SupermarketWithCategories',
}
}
} }
static AUTOMATION = { static AUTOMATION = {

View File

@ -176,31 +176,11 @@ export const ApiMixin = {
methods: { methods: {
genericAPI: function(model, action, options) { genericAPI: function(model, action, options) {
let setup = getConfig(model, action) let setup = getConfig(model, action)
if (setup?.config?.function) {
return specialCases[setup.config.function](action, options, setup)
}
let func = setup.function let func = setup.function
let config = setup?.config ?? {} let parameters = buildParams(options, setup)
let params = setup?.params ?? []
let parameters = []
let this_value = undefined
params.forEach(function (item, index) {
if (Array.isArray(item)) {
this_value = {}
// if the value is an array, convert it to a dictionary of key:value
// filtered based on OPTIONS passed
// maybe map/reduce is better?
for (const [k, v] of Object.entries(options)) {
if (item.includes(k)) {
this_value[k] = formatParam(config?.[k], v, options)
}
}
} else {
this_value = formatParam(config?.[item], options?.[item] ?? undefined, options)
}
// if no value is found so far, get the default if it exists
if (this_value === undefined) {
this_value = getDefault(config?.[item], options)
}
parameters.push(this_value)
});
let apiClient = new ApiApiFactory() let apiClient = new ApiApiFactory()
return apiClient[func](...parameters) return apiClient[func](...parameters)
}, },
@ -248,6 +228,33 @@ function formatParam(config, value, options) {
} }
return value return value
} }
function buildParams(options, setup) {
let config = setup?.config ?? {}
let params = setup?.params ?? []
let parameters = []
let this_value = undefined
params.forEach(function (item, index) {
if (Array.isArray(item)) {
this_value = {}
// if the value is an array, convert it to a dictionary of key:value
// filtered based on OPTIONS passed
// maybe map/reduce is better?
for (const [k, v] of Object.entries(options)) {
if (item.includes(k)) {
this_value[k] = formatParam(config?.[k], v, options)
}
}
} else {
this_value = formatParam(config?.[item], options?.[item] ?? undefined, options)
}
// if no value is found so far, get the default if it exists
if (this_value === undefined) {
this_value = getDefault(config?.[item], options)
}
parameters.push(this_value)
});
return parameters
}
function getDefault(config, options) { function getDefault(config, options) {
let value = undefined let value = undefined
value = config?.default ?? undefined value = config?.default ?? undefined
@ -429,28 +436,58 @@ export const CardMixin = {
const specialCases = { const specialCases = {
handleSuperMarketCategory: function(updatedRelationships, supermarket) { // the supermarket API requires chaining promises together, instead of trying to make
let API = ApiMixin.methods.genericAPI // this use case generic just treat it as a unique use case
if (updatedRelationships.length === 0) { SupermarketWithCategories: function(action, options, setup) {
return let API = undefined
let GenericAPI = ApiMixin.methods.genericAPI
let params = []
if (action.function === 'partialUpdate') {
API = GenericAPI
params = [Models.SUPERMARKET, Actions.FETCH, {'id': options.id}]
} else if (action.function === 'create') {
API = new ApiApiFactory()[setup.function]
params = buildParams(options, setup)
} }
// get current relationship mappings
API(Models.SUPERMARKET, Actions.FETCH, {'id': supermarket.id}).then((result) => { return API(...params).then((result) => {
let currentRelationships = result.data.category_to_supermarket // either get the supermarket or create the supermarket (but without the category relations)
let removed = currentRelationships.map(x => x.id).filter(x => !updatedRelationships.map(x => x.id).includes(x)) return result.data
removed.forEach(x => { }).then((result) => {
API(Models.SHOPPING_CATEGORY_RELATION, Actions.DELETE, {'id': x})//.then((result)=> console.log('delete', result)) // delete, update or change all of the category/relations
let id = result.id
let existing_categories = result.category_to_supermarket
let updated_categories = options.category_to_supermarket
let promises = []
// if the 'category.name' key does not exist on the updated_categories, the categories were not updated
if (updated_categories?.[0]?.category?.name) {
// list of category relationship ids that are not part of the updated supermarket
let removed_categories = existing_categories.filter(x => !updated_categories.map(x => x.category.id).includes(x.category.id))
let added_categories = updated_categories.filter(x => !existing_categories.map(x => x.category.id).includes(x.category.id))
let changed_categories = updated_categories.filter(x => existing_categories.map(x => x.category.id).includes(x.category.id))
removed_categories.forEach(x => {
promises.push(GenericAPI(Models.SHOPPING_CATEGORY_RELATION, Actions.DELETE, {'id': x.id}))
}) })
let item = {'supermarket': supermarket.id} let item = {'supermarket': id}
updatedRelationships.forEach(x => { added_categories.forEach(x => {
item.order = x.order item.order = x.order
item.category = {'id': x.category.id, 'name': x.category.name} item.category = {'id': x.category.id, 'name': x.category.name}
if (x.id) { promises.push(GenericAPI(Models.SHOPPING_CATEGORY_RELATION, Actions.CREATE, item))
item.id = x.id })
API(Models.SHOPPING_CATEGORY_RELATION, Actions.UPDATE, item)//.then((result)=> console.log('update', result)) changed_categories.forEach(x => {
} else { item.id = x?.id ?? existing_categories.find(y => y.category.id === x.category.id).id;
API(Models.SHOPPING_CATEGORY_RELATION, Actions.CREATE, item)//.then((result)=> console.log('create', result)) item.order = x.order
item.category = {'id': x.category.id, 'name': x.category.name}
promises.push(GenericAPI(Models.SHOPPING_CATEGORY_RELATION, Actions.UPDATE, item))
})
} }
return Promise.all(promises).then(() => {
// finally get and return the Supermarket which everything downstream is expecting
return GenericAPI(Models.SUPERMARKET, Actions.FETCH, {'id': id})
}) })
}) })
} }