File: D:/HostingSpaces/SBogers10/shop.komma.nl/resources/js/store/modules/properties.js
import ErrorHandler from "../../errorHandler";
import PropertyService from "../../services/propertyService";
import {requestThrottleGetters, requestThrottleMutations, requestThrottleState} from "../composables/requestThrottle";
import { States } from "../../components/vue/properties/resources/baseResource";
import Vue from 'Vue'
import Property from "../../components/vue/properties/resources/property";
import Value from "../../components/vue/properties/resources/value";
import KeyValueTranslation from "../../components/vue/properties/resources/translation";
const propertyService = new PropertyService();
/**
* @type {{requiredPropertyKeys: PropertyKey[], keyTranslations: KeyValueTranslation[], valueTranslations: KeyValueTranslation[], autocomplete: {}, currentPropertizableProperties: Property[], requests: string[], properties: Property[]}}
*/
export const propertyState = {
autocomplete: {},
...requestThrottleState,
requiredPropertyKeys: [], //The keys that the user is required to have on the propertizable
currentPropertizableProperties: [], //The current properties of for example a product, product group etc.
propertyKeys: [], //All property keys. Note, may not but could be used by any of the properties.
properties: [], //All properties
keyTranslations: [], //All property key translations
valueTranslations: [] //All property value translations
}
export const propertyMutations = {
...requestThrottleMutations,
storeCurrentPropertizableProperties(state, data) {
Vue.set(state, 'currentPropertizableProperties', data)
},
addPropertyToCurrentPropertizableProperties(state, data) {
state.currentPropertizableProperties.push(data); //Also see: https://vuejs.org/v2/guide/list.html#Array-Change-Detection
},
storeProperties(state, data) {
state.properties = data;
},
storePropertyKeys(state, data) {
state.propertyKeys = data;
},
storeRequiredPropertyKeys(state, data) {
const {requiredPropertyKeys} = data;
state.requiredPropertyKeys = requiredPropertyKeys;
},
updateRequiredPropertyStates(state, data) {
//Get the ids of the required property keys
const requiredPropertyKeyIds = state.requiredPropertyKeys.map(requiredPropertyKey => requiredPropertyKey.id);
//Only use the required properties
const requiredProps = state.currentPropertizableProperties.filter(prop => !!prop.is_required);
requiredProps.forEach((prop) => {
//Check if their keys still really are required. We can determine this by looking at required keys.
//If they are not required anymore we mark them as not required. This will "move" them to free property attributes.
if(requiredPropertyKeyIds.indexOf(prop.key.id) === -1) {
prop.is_required = 0;
if(prop.state !== States.NEW || prop.state !== States.DELETED) prop.state = States.DIRTY;
}
})
},
storeKeyTranslations(state, data) {
Vue.set(state, 'keyTranslations', data)
},
storeValueTranslations(state, data) {
Vue.set(state, 'valueTranslations', data)
},
updateDisplayProperty(state, displayProperty) {
let property = state.currentPropertizableProperties.find(property => property.id === displayProperty.id);
property.state = displayProperty.state;
let keyTranslation = propertyService.propertyKeyTranslationForIso2UsingProperty(property, displayProperty.iso2)
let valueTranslation = propertyService.propertyValueTranslationForIso2(property, displayProperty.iso2)
if(keyTranslation) keyTranslation.name = displayProperty.key
if(!valueTranslation) {
console.log('no translation found');
//Create a property value if the property does not have any values. Else we use the first value we find.
let value = null;
if(property.values.length === 0) {
console.log('no value found. making new one');
value = new Value();
property.values.push(value);
}
else value = property.values[0];
//Create a new value translation for it
valueTranslation = new KeyValueTranslation();
valueTranslation.language.iso_2 = displayProperty.iso2;
valueTranslation.state = States.NEW;
valueTranslation.name = displayProperty.value
//Add it to the values translations
value.translations.push(valueTranslation);
} else {
console.log('translation found');
if(valueTranslation.state !== States.NEW) valueTranslation.state = States.DIRTY;
valueTranslation.name = displayProperty.value
}
},
remove(state, ids) {
return state.currentPropertizableProperties.filter(currentPropertizableProperty => {
return ids.indexOf(currentPropertizableProperty.id) !== -1
}).forEach((property, index) => {
if(property.state !== States.NEW) {
//Mark the property as to be deleted by the backend when the users presses save
property.state = States.DELETED;
} else {
//Delete the property from the store since it does not exist in the backend, therefore does not have to be created, therefore then does not have to be deleted.
state.currentPropertizableProperties.splice(index, 1);
}
})
},
add(state, {property}) {
state.currentPropertizableProperties.push(property)
},
addTranslationToPropertiesKey(state, {propertizableId, propertizableType, property, translation}) {
//Get the propertizable
const propertizable = state.currentPropertizableProperties.find((propertizable) => {
return propertizable.id === propertizableId && propertizable.type === propertizableType
})
//Find the property in that propertizable
let propertizableProperty = propertizable.properties.find((propertizableProperty) => {
return propertizableProperty.id === property.id;
})
//Add the translation to it.
propertizableProperty.key.translations.push(translation);
}
};
export const propertyGetters = {
...requestThrottleGetters,
/**
* @param state
* @return
*/
propertiesForPropertizable(state) {
/** @param {boolean|undefined} required */
return function(required) {
if(typeof required === 'undefined') return state.currentPropertizableProperties;
return state.currentPropertizableProperties.filter((property => {
return !!property.is_required === required
}));
}
},
propertyIdsForPropertizable(state, getters) {
return function(required) {
return getters.propertiesForPropertizable(required).map(function(property) {
return property.id;
})
}
},
propertyKeysForPropertizable(state, getters) {
return function(required) {
return getters.propertiesForPropertizable(required).map(function(property) {
return property.key;
})
}
},
propertiesForPropertizableAsStringyfiedJson(state, getters) {
return function(required) {
return JSON.stringify(getters.propertiesForPropertizable(required))
}
},
displayPropertiesForPropertizable(state, getters) {
return function(iso2, required) {
if(!iso2) return [];
return getters.propertiesForPropertizable(required).map(function (property) {
const keyTranslation = propertyService.propertyKeyTranslationForIso2UsingProperty(property, iso2);
const valueTranslation = propertyService.propertyValueTranslationForIso2(property, iso2);
return {
id: property.id,
state: property.state,
iso2: iso2,
key: keyTranslation ? keyTranslation.name : '',
value: valueTranslation ? valueTranslation.name : '',
}
});
}
},
displayPropertyKeys(state, getters) {
return function(iso2) {
if(!iso2) return [];
return getters.propertyKeys(iso2).map((propertyKey) => {
const keyTranslation = propertyService.propertyKeyTranslationForIso2UsingPropertyKey(propertyKey, iso2);
return {
id: propertyKey.id,
iso2: iso2,
name: keyTranslation ? keyTranslation.name : '',
}
})
}
},
displayRequiredPropertyKeys(state, getters) {
return function(iso2) {
if(!iso2) return [];
return getters.requiredPropertyKeys(iso2).map((requiredPropertyKey) => {
const keyTranslation = propertyService.propertyKeyTranslationForIso2UsingPropertyKey(requiredPropertyKey, iso2);
return {
id: requiredPropertyKey.id,
iso2: iso2,
name: keyTranslation ? keyTranslation.name : '',
}
})
}
},
propertiesByKeyIdWithDisplayName(state, getters) {
return function() {
return state.properties.reduce((selectData, property) => {
if(property.hasOwnProperty('id')) selectData[property.id] = '';
else return selectData;
if(
property.hasOwnProperty('attributes') &&
property.hasOwnProperty('keyNames') &&
typeof property.keyNames === 'string'
) selectData[property.id] = property.keyNames;
return selectData;
}, {})
}
},
propertiesByPropertyIdWithDisplayName(state, getters) {
return function() {
return state.properties.reduce(
/**
* @param {Property} property
* @param {object} selectData
**/
(selectData, property) => {
if(!property.key) {
return;
}
const values = Object.values(selectData);
const keyNamesInSelectData = values.indexOf(property.key.names) !== -1
if(!keyNamesInSelectData) selectData[property.id] = property.key.names;
return selectData;
}, {})
}
},
propertiesKeysByIdWithDisplayName(state, getters) {
return function() {
return state.propertyKeys.reduce(
/**
* @param {Key} key
* @param {object} selectData
**/
(selectData, key) => {
const values = Object.values(selectData);
const keyNamesInSelectData = values.indexOf(key.names) !== -1
if(!keyNamesInSelectData) selectData[key.id] = key.names;
return selectData;
}, {})
}
},
requiredPropertyKeys(state, getters) {
return function(iso2) {
return state.requiredPropertyKeys.filter((requiredPropertyKey) => {
return propertyService.propertyKeyTranslationForIso2UsingPropertyKey(requiredPropertyKey, iso2);
})
}
},
propertyKeys(state, getters) {
return function(iso2) {
return state.propertyKeys.filter((propertyKey) => {
return propertyService.propertyKeyTranslationForIso2UsingPropertyKey(propertyKey, iso2);
})
}
},
valueTranslations(state, getters) {
return function() {
return state.valueTranslations;
}
},
keyTranslations(state, getters) {
return function() {
return state.keyTranslations;
}
}
};
export const propertyActions = {
loadProperties({ commit, getters }) {
commit('requesting', 'loadProperties')
let promise = propertyService.properties().then(
/** @param {Property[]} properties */
(properties) => {
commit('storeProperties', properties);
}
);
promise.catch(ErrorHandler.logFor('loadProperties')).finally(() => {
commit('clearRequest', 'loadProperties')
})
return promise;
},
loadPropertyKeys({ commit, getters }) {
commit('requesting', 'loadPropertyKeys')
let promise = propertyService.propertyKeys().then(
/** @param {Property[]} properties */
(properties) => {
commit('storePropertyKeys', properties);
}
);
promise.catch(ErrorHandler.logFor('loadPropertyKeys')).finally(() => {
commit('clearRequest', 'loadPropertyKeys')
})
return promise;
},
loadPropertyKeyValueTranslations({ commit, getters }, iso_2) {
['keyTranslations', 'valueTranslations'].forEach((type) => {
commit('requesting', 'loadPropertyKeyValueTranslations')
let promise = propertyService[type](iso_2).then((response) => {
if(!response.hasOwnProperty('data') || !response.data.hasOwnProperty('data')) return;
const upperCaseFirstType = type.charAt(0).toUpperCase() + type.slice(1)
commit('store'+upperCaseFirstType, response.data.data)
})
promise.catch(ErrorHandler.logFor('loadPropertyKeyValueTranslations')).finally(() => {
commit('clearRequest', 'loadPropertyKeyValueTranslations')
})
return promise;
})
},
create({ commit, getters }, data) {
commit('requesting', 'create')
let promise = propertyService.create(data);
promise.catch(ErrorHandler.logFor('create')).finally(() => {
commit('clearRequest', 'create')
})
return promise.then((response) => {
if (!response.hasOwnProperty('data') || !response.data.hasOwnProperty('data')) return;
return response.data.data;
});
},
createBasedOnExisting({ commit, getters }, data) {
commit('requesting', 'createBasedOnExisting')
let promise = propertyService.createBasedOnExisting(data);
promise.catch(ErrorHandler.logFor('createBasedOnExisting')).finally(() => {
commit('clearRequest', 'createBasedOnExisting')
})
return promise.then((response) => {
if (!response.hasOwnProperty('data') || !response.data.hasOwnProperty('data')) return;
return response.data.data;
});
},
loadRequiredKeys({ commit, getters, state, rootGetters }, data) {
const {categoriesCsv} = data;
if(categoriesCsv === '') {
commit('storeRequiredPropertyKeys', {requiredPropertyKeys: [], ...data})
commit('updateRequiredPropertyStates');
return;
}
commit('requesting', 'loadRequiredKeys')
let promise = propertyService.requiredKeysTranslations(categoriesCsv)
promise.catch(ErrorHandler.logFor('loadRequiredKeys')).finally(() => {
commit('clearRequest', 'loadRequiredKeys')
})
promise.then(async function(requiredPropertyKeys) {
commit('storeRequiredPropertyKeys', {requiredPropertyKeys: requiredPropertyKeys, ...data})
commit('updateRequiredPropertyStates');
//Create and commit new properties if they are required, but not yet added to the currentPropertizableProperties state
state.requiredPropertyKeys.forEach((requiredPropertyKey) => {
const existingRequiredPropertizablePropertyKeys = getters.propertyKeysForPropertizable(true);
const existingRequiredPropertizablePropertyKeyIds = existingRequiredPropertizablePropertyKeys.map((key) => key.id);
if(existingRequiredPropertizablePropertyKeyIds.indexOf(requiredPropertyKey.id) === -1) {
//requiredPropertyKey not found in any of the currentPropertizableProperties.
//Create a new required property with key id the same as requiredPropertyKey.id and is_required = 1
const property = new Property()
property.is_required = true;
property.key = requiredPropertyKey;
commit('add', {categoriesCsv, property});
}
})
})
return promise;
}
};
export default {
namespaced: true,
state: { ...propertyState },
actions: { ...propertyActions },
getters: { ...propertyGetters },
mutations: { ...propertyMutations }
}