Skip to content

Commit 584af08

Browse files
authored
Merge pull request #1664 from commercetools/sync-action-for-assets
feat(sync-actions): add sync actions for assets
2 parents 6be808c + e2d2301 commit 584af08

File tree

3 files changed

+414
-85
lines changed

3 files changed

+414
-85
lines changed

packages/sync-actions/src/product-actions.js

Lines changed: 150 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import {
1010
} from './utils/common-actions'
1111
import createBuildArrayActions, {
1212
ADD_ACTIONS,
13-
CHANGE_ACTIONS,
1413
REMOVE_ACTIONS,
1514
} from './utils/create-build-array-actions'
1615
import findMatchingPairs from './utils/find-matching-pairs'
@@ -26,6 +25,14 @@ export const baseActionsList = [
2625
{ action: 'setKey', key: 'key' },
2726
]
2827

28+
export const baseAssetActionsList = [
29+
{ action: 'setAssetKey', key: 'key', actionKey: 'assetKey' },
30+
{ action: 'changeAssetName', key: 'name' },
31+
{ action: 'setAssetDescription', key: 'description' },
32+
{ action: 'setAssetTags', key: 'tags' },
33+
{ action: 'setAssetSources', key: 'sources' },
34+
]
35+
2936
export const metaActionsList = [
3037
{ action: 'setMetaTitle', key: 'metaTitle' },
3138
{ action: 'setMetaDescription', key: 'metaDescription' },
@@ -41,6 +48,15 @@ export const referenceActionsList = [
4148
* HELPER FUNCTIONS
4249
*/
4350

51+
const getIsAddAction = (key, resource) =>
52+
REGEX_NUMBER.test(key) && Array.isArray(resource) && resource.length
53+
54+
const getIsUpdateAction = (key, resource) =>
55+
REGEX_NUMBER.test(key) && Object.keys(resource).length
56+
57+
const getIsRemoveAction = (key, resource) =>
58+
REGEX_UNDERSCORE_NUMBER.test(key) && Number(resource[2]) === 0
59+
4460
function _buildSkuActions(variantDiff, oldVariant) {
4561
if ({}.hasOwnProperty.call(variantDiff, 'sku')) {
4662
const newValue = diffpatcher.getDeltaValue(variantDiff.sku)
@@ -256,45 +272,48 @@ function _buildVariantPricesAction(
256272
oldVariant.prices,
257273
newVariant.prices
258274
)
259-
if (REGEX_NUMBER.test(key)) {
260-
if (Array.isArray(price) && price.length) {
261-
// Remove read-only fields
262-
const patchedPrice = price.map((p) => {
263-
const shallowClone = { ...p }
264-
if (enableDiscounted !== true) delete shallowClone.discounted
265-
return shallowClone
266-
})
275+
if (getIsAddAction(key, price)) {
276+
// Remove read-only fields
277+
const patchedPrice = price.map((p) => {
278+
const shallowClone = { ...p }
279+
if (enableDiscounted !== true) delete shallowClone.discounted
280+
return shallowClone
281+
})
282+
283+
addPriceActions.push({
284+
action: 'addPrice',
285+
variantId: oldVariant.id,
286+
price: diffpatcher.getDeltaValue(patchedPrice),
287+
})
288+
return
289+
}
267290

268-
addPriceActions.push({
269-
action: 'addPrice',
270-
variantId: oldVariant.id,
271-
price: diffpatcher.getDeltaValue(patchedPrice),
272-
})
273-
} else if (Object.keys(price).length) {
274-
// Remove the discounted field and make sure that the price
275-
// still has other values, otherwise simply return
276-
const filteredPrice = { ...price }
277-
if (enableDiscounted !== true) delete filteredPrice.discounted
278-
if (Object.keys(filteredPrice).length) {
279-
// At this point price should have changed, simply pick the new one
280-
const newPrice = { ...newObj }
281-
if (enableDiscounted !== true) delete newPrice.discounted
282-
283-
changePriceActions.push({
284-
action: 'changePrice',
285-
priceId: oldObj.id,
286-
price: newPrice,
287-
})
288-
}
289-
}
290-
} else if (REGEX_UNDERSCORE_NUMBER.test(key))
291-
if (Number(price[2]) === 0) {
292-
// price removed
293-
removePriceActions.push({
294-
action: 'removePrice',
291+
if (getIsUpdateAction(key, price)) {
292+
// Remove the discounted field and make sure that the price
293+
// still has other values, otherwise simply return
294+
const filteredPrice = { ...price }
295+
if (enableDiscounted !== true) delete filteredPrice.discounted
296+
if (Object.keys(filteredPrice).length) {
297+
// At this point price should have changed, simply pick the new one
298+
const newPrice = { ...newObj }
299+
if (enableDiscounted !== true) delete newPrice.discounted
300+
301+
changePriceActions.push({
302+
action: 'changePrice',
295303
priceId: oldObj.id,
304+
price: newPrice,
296305
})
297306
}
307+
return
308+
}
309+
310+
if (getIsRemoveAction(key, price)) {
311+
// price removed
312+
removePriceActions.push({
313+
action: 'removePrice',
314+
priceId: oldObj.id,
315+
})
316+
}
298317
})
299318

300319
return [addPriceActions, changePriceActions, removePriceActions]
@@ -381,37 +400,84 @@ function toVariantIdentifier(variant) {
381400
return id ? { variantId: id } : { sku }
382401
}
383402

384-
function _buildVariantAssetsActions(diff, oldObj, newObj) {
385-
const handler = createBuildArrayActions('assets', {
386-
[ADD_ACTIONS]: (newAsset) => ({
387-
action: 'addAsset',
388-
asset: newAsset,
389-
...toVariantIdentifier(newObj),
390-
}),
391-
[REMOVE_ACTIONS]: (oldAsset) => ({
392-
action: 'removeAsset',
393-
...toAssetIdentifier(oldAsset),
394-
...toVariantIdentifier(oldObj),
395-
}),
396-
[CHANGE_ACTIONS]: (oldAsset, newAsset) =>
397-
// here we could use more atomic update actions (e.g. changeAssetName)
398-
// but for now we use the simpler approach to first remove and then
399-
// re-add the asset - which reduces the code complexity
400-
[
401-
{
402-
action: 'removeAsset',
403+
function _buildVariantAssetsActions(diffAssets, oldVariant, newVariant) {
404+
const assetActions = []
405+
406+
// generate a hashMap to be able to reference the right asset from both ends
407+
const matchingAssetPairs = findMatchingPairs(
408+
diffAssets,
409+
oldVariant.assets,
410+
newVariant.assets
411+
)
412+
413+
forEach(diffAssets, (asset, key) => {
414+
const { oldObj: oldAsset, newObj: newAsset } = extractMatchingPairs(
415+
matchingAssetPairs,
416+
key,
417+
oldVariant.assets,
418+
newVariant.assets
419+
)
420+
421+
if (getIsAddAction(key, asset)) {
422+
assetActions.push({
423+
action: 'addAsset',
424+
asset: diffpatcher.getDeltaValue(asset),
425+
...toVariantIdentifier(newVariant),
426+
position: Number(key),
427+
})
428+
return
429+
}
430+
431+
if (getIsUpdateAction(key, asset)) {
432+
// todo add changeAssetOrder
433+
const basicActions = buildBaseAttributesActions({
434+
actions: baseAssetActionsList,
435+
diff: asset,
436+
oldObj: oldAsset,
437+
newObj: newAsset,
438+
}).map((action) => {
439+
// in case of 'setAssetKey' then the identifier will be only 'assetId'
440+
if (action.action === 'setAssetKey') {
441+
return {
442+
...action,
443+
...toVariantIdentifier(oldVariant),
444+
assetId: oldAsset.id,
445+
}
446+
}
447+
448+
return {
449+
...action,
450+
...toVariantIdentifier(oldVariant),
403451
...toAssetIdentifier(oldAsset),
404-
...toVariantIdentifier(oldObj),
405-
},
406-
{
407-
action: 'addAsset',
408-
asset: newAsset,
409-
...toVariantIdentifier(newObj),
410-
},
411-
],
452+
}
453+
})
454+
assetActions.push(...basicActions)
455+
456+
if (asset.custom) {
457+
const customActions = actionsMapCustom(asset, newAsset, oldAsset, {
458+
actions: {
459+
setCustomType: 'setAssetCustomType',
460+
setCustomField: 'setAssetCustomField',
461+
},
462+
...toVariantIdentifier(oldVariant),
463+
...toAssetIdentifier(oldAsset),
464+
})
465+
assetActions.push(...customActions)
466+
}
467+
468+
return
469+
}
470+
471+
if (getIsRemoveAction(key, asset)) {
472+
assetActions.push({
473+
action: 'removeAsset',
474+
...toAssetIdentifier(oldAsset),
475+
...toVariantIdentifier(oldVariant),
476+
})
477+
}
412478
})
413479

414-
return handler(diff, oldObj, newObj)
480+
return assetActions
415481
}
416482

417483
/**
@@ -521,7 +587,8 @@ export function actionsMapCategoryOrderHints(diff) {
521587
}
522588

523589
export function actionsMapAssets(diff, oldObj, newObj, variantHashMap) {
524-
let actions = []
590+
let allAssetsActions = []
591+
525592
const { variants } = diff
526593

527594
if (variants)
@@ -532,16 +599,21 @@ export function actionsMapAssets(diff, oldObj, newObj, variantHashMap) {
532599
oldObj.variants,
533600
newObj.variants
534601
)
535-
if (REGEX_NUMBER.test(key) && !Array.isArray(variant)) {
602+
if (
603+
variant.assets &&
604+
(REGEX_UNDERSCORE_NUMBER.test(key) || REGEX_NUMBER.test(key))
605+
) {
536606
const assetActions = _buildVariantAssetsActions(
537-
variant,
607+
variant.assets,
538608
oldVariant,
539609
newVariant
540610
)
541-
if (assetActions) actions = actions.concat(assetActions)
611+
612+
allAssetsActions = allAssetsActions.concat(assetActions)
542613
}
543614
})
544-
return actions
615+
616+
return allAssetsActions
545617
}
546618

547619
export function actionsMapAttributes(
@@ -635,19 +707,24 @@ export function actionsMapPrices(
635707
newObj.variants
636708
)
637709
if (REGEX_UNDERSCORE_NUMBER.test(key) || REGEX_NUMBER.test(key)) {
638-
const [a, c, r] = _buildVariantPricesAction(
710+
const [
711+
addPriceAction,
712+
changePriceAction,
713+
removePriceAction,
714+
] = _buildVariantPricesAction(
639715
variant.prices,
640716
oldVariant,
641717
newVariant,
642718
enableDiscounted
643719
)
644720

645-
addPriceActions = addPriceActions.concat(a)
646-
changePriceActions = changePriceActions.concat(c)
647-
removePriceActions = removePriceActions.concat(r)
721+
addPriceActions = addPriceActions.concat(addPriceAction)
722+
changePriceActions = changePriceActions.concat(changePriceAction)
723+
removePriceActions = removePriceActions.concat(removePriceAction)
648724
}
649725
})
650726

727+
// price actions need to be in this below order
651728
return changePriceActions.concat(removePriceActions).concat(addPriceActions)
652729
}
653730

packages/sync-actions/src/utils/action-map-custom.js

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -33,23 +33,23 @@ export default function actionsMapCustom(
3333
customProps = { actions: {} }
3434
) {
3535
const actions = []
36-
const priceId = customProps.priceId
37-
const actionGroup = { ...Actions, ...customProps.actions }
36+
const { actions: customPropsActions, ...options } = customProps
37+
const actionGroup = { ...Actions, ...customPropsActions }
3838

3939
if (!diff.custom) return actions
4040
if (hasSingleCustomFieldChanged(diff)) {
4141
// If custom is not defined on the new or old category
4242
const custom = diffpatcher.getDeltaValue(diff.custom, oldObj)
43-
actions.push({ action: actionGroup.setCustomType, priceId, ...custom })
43+
actions.push({ action: actionGroup.setCustomType, ...options, ...custom })
4444
} else if (hasCustomTypeChanged(diff)) {
4545
// If custom is set to an empty object on the new or old category
4646
const type = extractCustomType(diff, oldObj)
4747

48-
if (!type) actions.push({ action: actionGroup.setCustomType, priceId })
48+
if (!type) actions.push({ action: actionGroup.setCustomType, ...options })
4949
else if (type.id)
5050
actions.push({
5151
action: actionGroup.setCustomType,
52-
priceId,
52+
...options,
5353
type: {
5454
typeId: 'type',
5555
id: extractTypeId(type, newObj),
@@ -59,7 +59,7 @@ export default function actionsMapCustom(
5959
else if (type.key)
6060
actions.push({
6161
action: actionGroup.setCustomType,
62-
priceId,
62+
...options,
6363
type: {
6464
typeId: 'type',
6565
key: extractTypeKey(type, newObj),
@@ -69,7 +69,7 @@ export default function actionsMapCustom(
6969
} else if (haveMultipleCustomFieldsChanged(diff)) {
7070
const customFieldsActions = Object.keys(diff.custom.fields).map((name) => ({
7171
action: actionGroup.setCustomField,
72-
priceId,
72+
...options,
7373
name,
7474
value: extractFieldValue(newObj.custom.fields, name),
7575
}))

0 commit comments

Comments
 (0)