mirror of https://github.com/Requarks/wiki.git
NGPixel
6 years ago
3 changed files with 356 additions and 28 deletions
Split View
Diff Options
-
70client/components/admin/admin-groups-edit.vue
-
141client/components/common/criterias-item.vue
-
173client/components/common/criterias.vue
@ -0,0 +1,141 @@ |
|||
<template lang="pug"> |
|||
.criterias-item |
|||
//- Type |
|||
v-select(solo, :items='filteredCriteriaTypes', v-model='item.type', placeholder='Rule Type', ref='typeSelect') |
|||
template(slot='item', slot-scope='data') |
|||
v-list-tile-avatar |
|||
v-avatar(:color='data.item.color', size='40', tile): v-icon(color='white') {{ data.item.icon }} |
|||
v-list-tile-content |
|||
v-list-tile-title(v-html='data.item.text') |
|||
v-list-tile-sub-title.caption(v-html='data.item.description') |
|||
|
|||
//- Operator |
|||
v-select(solo, :items='filteredCriteriaOperators', v-model='item.operator', placeholder='Operator', :disabled='!item.type', :class='!item.type ? "blue-grey lighten-4" : ""') |
|||
template(slot='item', slot-scope='data') |
|||
v-list-tile-avatar |
|||
v-avatar.white--text(color='blue', size='30', tile) {{ data.item.icon }} |
|||
v-list-tile-content |
|||
v-list-tile-title(v-html='data.item.text') |
|||
|
|||
//- Value |
|||
v-select(v-if='item.type === "country"', solo, :items='countries', v-model='item.value', placeholder='Countries...', multiple, item-text='name', item-value='code') |
|||
v-text-field(v-else-if='item.type === "path"', solo, v-model='item.value', label='Path (e.g. /section)') |
|||
v-text-field(v-else-if='item.type === "date"', solo, @click.native.stop='dateActivator = true', v-model='item.value', label='YYYY-MM-DD', readonly) |
|||
v-text-field.blue-grey.lighten-4(v-else, solo, disabled) |
|||
|
|||
v-dialog(lazy, v-model='dateActivator', width='290px', ref='dateDialog') |
|||
v-date-picker(v-model='item.value', scrollable, color='primary') |
|||
v-btn(flat, color='primary' @click='$refs.dateDialog.save(date)', block) ok |
|||
|
|||
v-btn(icon, @click='remove'): v-icon(color='blue-grey') clear |
|||
</template> |
|||
|
|||
<script> |
|||
import _ from 'lodash' |
|||
|
|||
// import countriesQuery from 'gql/upsells-query-countries.gql' |
|||
|
|||
export default { |
|||
inject: ['allowedCriteriaTypes'], |
|||
props: { |
|||
value: { |
|||
type: Object, |
|||
default() { return {} } |
|||
}, |
|||
groupIndex: { |
|||
type: Number, |
|||
default() { return 0 } |
|||
}, |
|||
itemIndex: { |
|||
type: Number, |
|||
default() { return 0 } |
|||
} |
|||
}, |
|||
data() { |
|||
return { |
|||
item: { |
|||
operator: '', |
|||
type: '', |
|||
value: '' |
|||
}, |
|||
dateActivator: false, |
|||
dateDialog: false, |
|||
countries: [], |
|||
criteriaTypes: [ |
|||
{ text: 'Path', value: 'path', icon: 'space_bar', color: 'blue', description: 'Match the path of the document being viewed.' }, |
|||
{ text: 'Date', value: 'date', icon: 'date_range', color: 'blue', description: 'Match the current calendar day.' }, |
|||
{ text: 'Time', value: 'time', icon: 'access_time', color: 'blue', description: 'Match the current time of day.' }, |
|||
{ text: 'User Country', value: 'country', icon: 'public', color: 'red', description: `Match the user's country.` }, |
|||
{ text: 'User Group', value: 'group', icon: 'group', color: 'orange', description: 'Match the user group assignments.' } |
|||
], |
|||
criteriaOperators: { |
|||
country: [ |
|||
{ text: 'In', value: 'in', icon: '[...]' }, |
|||
{ text: 'Not In', value: 'notIn', icon: '[ x ]' } |
|||
], |
|||
path: [ |
|||
{ text: 'Matches Exactly', value: 'eq', icon: '=' }, |
|||
{ text: 'NOT Matches Exactly', value: 'ne', icon: '!=' }, |
|||
{ text: 'Starts With', value: 'sw', icon: 'x...' }, |
|||
{ text: 'NOT Starts With', value: 'nsw', icon: '!x...' }, |
|||
{ text: 'Ends With', value: 'ew', icon: '...x' }, |
|||
{ text: 'NOT Ends With', value: 'new', icon: '!...x' }, |
|||
{ text: 'Matches Regex', value: 'regexp', icon: '^x$' } |
|||
], |
|||
date: [ |
|||
{ text: 'On or After', value: 'gte', icon: '>=' }, |
|||
{ text: 'On or Before', value: 'lte', icon: '<=' } |
|||
], |
|||
time: [ |
|||
{ text: 'At or Later Than', value: 'gte', icon: '>=' }, |
|||
{ text: 'At or Before', value: 'lte', icon: '<=' } |
|||
], |
|||
group: [ |
|||
{ text: 'Is Part Of', value: 'in', icon: '[...]' }, |
|||
{ text: 'Is Not Part Of', value: 'notIn', icon: '[ x ]' } |
|||
] |
|||
} |
|||
} |
|||
}, |
|||
computed: { |
|||
filteredCriteriaOperators() { |
|||
return _.get(this.criteriaOperators, this.item.type, []) |
|||
}, |
|||
filteredCriteriaTypes() { |
|||
console.info(this.allowedCriteriaTypes) |
|||
return _.filter(this.criteriaTypes, c => _.includes(this.allowedCriteriaTypes, c.value)) |
|||
}, |
|||
itemType() { |
|||
return this.item.type |
|||
} |
|||
}, |
|||
watch: { |
|||
itemType(newValue, oldValue) { |
|||
this.item.operator = _.head(this.criteriaOperators[newValue]).value |
|||
this.item.value = '' |
|||
}, |
|||
item: { |
|||
handler(newValue, oldValue) { |
|||
this.$emit('update', this.groupIndex, this.itemIndex, this.item) |
|||
}, |
|||
deep: true |
|||
} |
|||
}, |
|||
mounted() { |
|||
if (!this.item.type) { |
|||
this.$refs.typeSelect.showMenu() |
|||
} |
|||
}, |
|||
methods: { |
|||
remove() { |
|||
this.$emit('remove', this.groupIndex, this.itemIndex) |
|||
} |
|||
} |
|||
// apollo: { |
|||
// countries: { |
|||
// query: countriesQuery, |
|||
// update: (data) => data.location.countries |
|||
// } |
|||
// } |
|||
} |
|||
</script> |
@ -0,0 +1,173 @@ |
|||
<template lang="pug"> |
|||
.criterias |
|||
transition-group(name='criterias-group', tag='div') |
|||
.criterias-group(v-for='(group, g) in groups', :key='g') |
|||
transition-group(name='criterias-item', tag='div') |
|||
criterias-item(v-for='(item, i) in group', :key='i', :item='item', :group-index='g', :item-index='i', @update='updateItem', @remove='removeItem') |
|||
.criterias-item-more |
|||
v-btn.ml-0(@click='addItem(group)', small, color='blue-grey lighten-2', dark, depressed) |
|||
v-icon(color='white', left) add |
|||
| Add condition |
|||
.criterias-group-more |
|||
v-btn(@click='addGroup', small, color='blue-grey lighten-1', dark, depressed) |
|||
v-icon(color='white', left) add |
|||
| Add condition group |
|||
</template> |
|||
|
|||
<script> |
|||
import CriteriasItem from './criterias-item.vue' |
|||
|
|||
export default { |
|||
components: { |
|||
CriteriasItem |
|||
}, |
|||
props: { |
|||
value: { |
|||
type: Array, |
|||
default() { return [] } |
|||
}, |
|||
types: { |
|||
type: Array, |
|||
default() { |
|||
return ['country', 'path', 'date', 'time', 'group'] |
|||
} |
|||
} |
|||
}, |
|||
provide () { |
|||
return { |
|||
allowedCriteriaTypes: this.types |
|||
} |
|||
}, |
|||
data() { |
|||
return { |
|||
dataGroups: this.value || [] |
|||
} |
|||
}, |
|||
computed: { |
|||
groups: { |
|||
get() { return this.dataGroups }, |
|||
set(grp) { |
|||
this.dataGroups = grp |
|||
} |
|||
} |
|||
}, |
|||
watch: { |
|||
dataGroups(newValue, oldValue) { |
|||
if (newValue !== oldValue) { |
|||
this.$emit('input', newValue) |
|||
} |
|||
} |
|||
}, |
|||
methods: { |
|||
addGroup() { |
|||
this.dataGroups.push([{}]) |
|||
}, |
|||
addItem(group) { |
|||
group.push({}) |
|||
}, |
|||
updateItem(groupIndex, itemIndex, item) { |
|||
console.info(item) |
|||
this.$set(this.dataGroups[groupIndex], itemIndex, item) |
|||
}, |
|||
removeItem(groupIndex, itemIndex) { |
|||
this.dataGroups[groupIndex].splice(itemIndex, 1) |
|||
if (this.dataGroups[groupIndex].length < 1) { |
|||
this.dataGroups.splice(groupIndex, 1) |
|||
} |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style lang="scss"> |
|||
.criterias { |
|||
&-group { |
|||
background-color: mc('blue-grey', '100'); |
|||
border-radius: 4px; |
|||
padding: 1rem; |
|||
position: relative; |
|||
|
|||
&-enter-active, &-leave-active { |
|||
transition: all .5s ease; |
|||
} |
|||
&-enter, &-leave-to { |
|||
opacity: 0; |
|||
} |
|||
|
|||
& + .criterias-group { |
|||
margin-top: 1rem; |
|||
|
|||
&::before { |
|||
content: 'OR'; |
|||
position: absolute; |
|||
display: inline-flex; |
|||
padding: 0 2rem; |
|||
top: -1.25rem; |
|||
left: 2rem; |
|||
background-color: mc('blue-grey', '100'); |
|||
color: mc('blue-grey', '700'); |
|||
font-weight: 600; |
|||
font-size: .9rem; |
|||
} |
|||
} |
|||
|
|||
&-more { |
|||
margin: .5rem 0 0 .4rem; |
|||
} |
|||
} |
|||
|
|||
&-item { |
|||
display: flex; |
|||
background-color: mc('blue-grey', '200'); |
|||
border-radius: 4px; |
|||
padding: .5rem; |
|||
|
|||
&-enter-active, &-leave-active { |
|||
transition: all .5s ease; |
|||
} |
|||
&-enter, &-leave-to { |
|||
opacity: 0; |
|||
} |
|||
|
|||
& + .criterias-item { |
|||
margin-top: .5rem; |
|||
position: relative; |
|||
|
|||
&::before { |
|||
content: 'AND'; |
|||
position: absolute; |
|||
width: 2rem; |
|||
height: 2rem; |
|||
border-radius: 50%; |
|||
display: flex; |
|||
justify-content: center; |
|||
align-items: center; |
|||
font-weight: 600; |
|||
color: mc('blue-grey', '700'); |
|||
font-size: .7rem; |
|||
background-color: mc('blue-grey', '100'); |
|||
left: -2rem; |
|||
top: -1.3rem; |
|||
} |
|||
} |
|||
|
|||
.input-group { |
|||
&:nth-child(1) { |
|||
flex: 0 1 350px; |
|||
} |
|||
|
|||
&:nth-child(2) { |
|||
flex: 0 1 250px; |
|||
} |
|||
|
|||
& + * { |
|||
margin-left: .5rem; |
|||
} |
|||
} |
|||
|
|||
&-more { |
|||
margin-top: .15rem; |
|||
} |
|||
} |
|||
} |
|||
</style> |
Write
Preview
Loading…
Cancel
Save