File: D:/HostingSpaces/SBogers10/shop.komma.nl/resources/js/components/vue/properties/FreeProperties.vue
<template>
<div>
<transition name="a-modal">
<div class="o-modal" v-if="modalOpened">
<div class="o-modal__content">
<h3 class="o-modal__header">{{ trans('KMS::properties').free_properties }}</h3>
<div class="o-modal__body">
<label class="radio" >
<input type="radio" :name="propertyTypeRadioName" value="existing" v-model="propertyType">
<span>{{ trans('KMS::properties').choose_existing_properties }}</span>
</label>
<multiselect
:disabled="propertyType !== 'existing'"
:values="this.propertiesKeysByIdWithDisplayName()"
@change="selectedExistingPropertyKeys = $event"
name="existing"
/>
<div class="new-properties">
<label class="radio">
<input type="radio" :name="propertyTypeRadioName" value="new" v-model="propertyType">
<span>{{ newPropertyLabel }}</span>
</label>
<div class="" v-if="propertyType !== 'existing'">
<label v-for="(languageHavingSite, index) in this.languagesHavingSites()">
<span>{{ trans('KMS::properties').name + ' ' + languageHavingSite.iso_2 }}</span>
<input type="text" v-model="newPropertyNames[index]" :list="valuesId">
</label>
</div>
</div>
<div class="button-row" :data-create-type="propertyType">
<button class="button" v-if="propertyType === 'existing'" type="button" @click="createBasedOnExisting()">{{ trans('KMS::properties').save }}</button>
<button class="button" v-if="propertyType !== 'existing'" type="button" @click="createProperty()" :disabled="addPropertyButtonDisabled">{{ trans('KMS::properties').add }}</button>
<button class="button button--subtle" type="button" @click="openModal(false)">{{ trans('KMS::properties').close }}</button>
</div>
</div>
</div>
</div>
</transition>
<div class="wrapper">
<label>{{ trans('KMS::properties').free_properties }}</label>
<table>
<tbody>
<tr v-for="displayProperty in this.displayPropertiesForPropertizable(this.iso_2, false)" :class="{ 'u-hidden': (displayProperty.state === 4) }" :data-id="displayProperty.id">
<td><span :list="keysId">{{ displayProperty.key }}</span></td>
<td><input aria-label="property" type="text" :value="displayProperty.value" @input="updatePropertyValue($event, displayProperty)" :list="valuesId" /></td>
<td><button class="trash" @click.prevent="remove(displayProperty.id)" title="Delete"></button></td>
</tr>
</tbody>
</table>
<button class="button" type="button" @click.prevent="openModal(true)">{{ trans('KMS::properties').add }}</button>
</div>
<datalist :id="valuesId">
<option v-for="valueTranslation in this.valueTranslations()" :value="valueTranslation.name"/>
</datalist>
<input type="hidden" :name="attributeKey" ref="real_input" :value="propertiesForPropertizableAsStringyfiedJson(false)">
</div>
</template>
<style lang="scss" scoped>
.wrapper {
margin-top: 16px;
padding-left: 45px;
}
label {
display: block;
font-size: .7rem;
color: #9ba0ae;
text-transform: uppercase;
font-weight: 500;
white-space: nowrap;
margin: 0;
}
table {
margin-bottom: 8px;
}
td {
&:first-child {
display: block;
margin-top: 9px;
margin-right: 60px;
font-size: .7rem;
color: #70778c;
font-weight: 700;
text-transform: uppercase;
white-space: nowrap;
}
}
input[type="text"] {
min-height: 40px;
background-color: #fff;
text-indent: 10px;
font-size: .7rem;
z-index: 99999;
display: block;
color: #32343a;
box-sizing: border-box;
width: 100%;
max-width: 500px;
border: 1px solid #d8dae2;
border-radius: 5px;
transition: border-color .25s ease-in-out,box-shadow .25s ease-in-out;
&:focus {
border-color: #3c8bf5;
outline: 0;
box-shadow: inset 0 1px 1px rgba(0,0,0,.075), inset 0 0 12px rgba(120,169,236,.3);
}
}
.button {
display: inline-block;
height: 40px;
padding: 0 40px;
background-color: #3289ff;
color: #fff;
font-size: .7rem;
font-family: Rubik, sans-serif;
vertical-align: top;
border-radius: 4px;
appearance: none;
border: none;
cursor: pointer;
transition: background-color .3s;
&:hover {
background-color: #006cfe;
}
&[disabled="disabled"] {
background-color: #aaaaaa;
cursor: not-allowed;
}
}
.button--subtle {
color: #1d2433;
background-color: #eceef3;
&:hover {
background-color: #d5d9e4;
}
}
.button-row {
display: flex;
justify-content: space-between;
margin-top: 16px;
}
.new-properties {
}
.radio {
margin-top: 8px;
margin-bottom: 8px;
}
</style>
<script>
import { mapGetters } from "vuex";
import PropertyService from "../../../services/propertyService";
import { States } from "./resources/baseResource";
import Multiselect from "../forms/multiselect";
import Property from "./resources/property";
import KeyValueTranslation from "./resources/translation";
let propertyService = new PropertyService();
export default {
components: {
Multiselect
},
props: {
attributeKey: {
required: true,
type: String
},
iso_2: {
required: true,
type: String
},
},
data: function() {
return {
newPropertyNames: [],
selectedExistingPropertyKeys: [],
//Add property modal data
propertyType: 'existing',
modalOpened: false,
propertizable_id: null,
propertizable_type: null,
}
},
methods: {
updatePropertyValue(event, property) {
property.value = event.target.value;
if(property.state !== States.NEW) property.state = States.DIRTY
this.$store.commit('properties/updateDisplayProperty', property)
},
openModal(open) {
this.newPropertyNames = []; //Clear state
this.modalOpened = open;
},
createBasedOnExisting() {
const store = this.$store
this.selectedExistingPropertyKeys.map(existingId => parseInt(existingId)).forEach(existingId => {
//Build data to send to the backend, that will create a new property
let key = store.state.properties.propertyKeys.find((key) => key.id === existingId)
const property = new Property();
property.key = key;
this.$store.commit('properties/addPropertyToCurrentPropertizableProperties', property);
this.newPropertyNames = [];
this.openModal(false);
});
},
remove(propertyId) {
this.$store.commit('properties/remove', [propertyId])
},
createProperty() {
console.log('create new property')
//Build data to send to the backend, that will create a new property
const property = new Property();
const languages = this.languagesHavingSites();
let languagesHavingSitesCount = languages.length;
for(let index = 0; index < languagesHavingSitesCount; index++) {
if(typeof this.newPropertyNames[index] === 'undefined') break;
let translation = new KeyValueTranslation();
translation.language.id = languages[index].id
translation.language.iso_2 = languages[index].iso_2
translation.name = this.newPropertyNames[index];
property.key.translations.push(translation);
}
this.$store.commit('properties/addPropertyToCurrentPropertizableProperties', property);
console.log('stored')
this.newPropertyNames = [];
this.openModal(false);
}
},
computed: {
...mapGetters({
trans: "g11n/translation/translation",
languagesHavingSites: "sites/languagesHavingSites",
propertiesByKeyId: "properties/propertiesByKeyIdWithDisplayName",
propertiesForPropertizableAsStringyfiedJson: "properties/propertiesForPropertizableAsStringyfiedJson",
displayPropertiesForPropertizable: "properties/displayPropertiesForPropertizable",
displayPropertyKeys: "properties/displayPropertyKeys",
propertyIdsForPropertizable: "properties/propertyIdsForPropertizable",
propertiesKeysByIdWithDisplayName: "properties/propertiesKeysByIdWithDisplayName",
valueTranslations: "properties/valueTranslations",
keyTranslations: "properties/keyTranslations",
}),
valuesId: function() {
return this.attributeKey + '|values'
},
keysId: function() {
return this.attributeKey + '|keys'
},
propertyTypeRadioName: function() {
return this.attributeKey + '|property_type';
},
addPropertyButtonDisabled: function() {
if(!Array.isArray(this.newPropertyNames)) return true;
const disabledByLengthConditions = (
this.newPropertyNames.length === 0 ||
this.newPropertyNames.length !== this.languagesHavingSites().length
)
const emptyPropertiesCount = this.newPropertyNames.filter((name) => {
return name.trim() === '';
}).length
return disabledByLengthConditions || emptyPropertiesCount > 0;
},
//"Add property modal data
newPropertyLabel: function() {
return (this.propertyType === 'existing') ? this.trans('KMS::properties').section.new : this.trans('KMS::properties').name_new;
},
},
};
</script>