Skip to content

Commit

Permalink
[wizard] Redirect app: add filters.
Browse files Browse the repository at this point in the history
  • Loading branch information
mayakokits authored and torotil committed Jan 11, 2018
1 parent da115a1 commit ae57129
Show file tree
Hide file tree
Showing 5 changed files with 210 additions and 7 deletions.
35 changes: 35 additions & 0 deletions campaignion_wizard/redirects_app/README.md
Expand Up @@ -22,6 +22,41 @@ JSON Response:

### Persist data on form submit

``` json
{
"redirects": [
{
"id": null,
"label": "My internal label",
"destination": "node/20",
"prettyDestination": "Pretty title of my node (20)",
"filters": [
{
"id": null,
"type": "opt-in",
"value": true
},
{
"id": null,
"type": "submission-field",
"field": "f_name",
"operator": "contains",
"value": "foo"
}
]
}
]
}
```

Operators:

* `==` is
* `!=` is not
* `contains` contains
* `!contains` does not contain
* `regexp` matches regular expression
* `!regexp` doesn’t match regular expression

## Build Setup

Expand Down
140 changes: 140 additions & 0 deletions campaignion_wizard/redirects_app/src/components/FilterEditor.vue
@@ -0,0 +1,140 @@
<template lang="html">
<section class="pra-filter-editor">

<header>
<ElDropdown trigger="click" menu-align="start">
<ElButton>
{{ text('Add filter') }}<i class="el-icon-caret-bottom el-icon--right"></i>
</ElButton>
<ElDropdownMenu slot="dropdown">
<ElDropdownItem :disabled="optInUsed" @click.native="addFilter('opt-in')">{{ text('opt-in filter') }}</ElDropdownItem>
<ElDropdownItem :disabled="!fields.length" @click.native="addFilter('submission-field')">{{ text('submission-field filter') }}</ElDropdownItem>
</ElDropdownMenu>
</ElDropdown>
</header>

<ul class="pra-filters">
<li v-for="(filter, index) in f" :key="index" class="pra-filter">

<span v-if="index === 0" class="pra-logical-connective">{{ text('If') }}</span>
<span v-else class="pra-logical-connective">{{ text('and') }}</span>

<template v-if="filter.type === 'opt-in'" class="">
{{ text('supporter') }}
<ElSelect v-model="filter.value">
<ElOption :label="text('has')" :value="true"/>
<ElOption :label="text('has not')" :value="false"/>
</ElSelect>
{{ text('opted in') }}
</template>

<template v-else>
<ElSelect v-model="filter.field">
<ElOption v-for="field in fields" :key="field.id" :label="field.label" :value="field.id"/>
</ElSelect>
<ElSelect v-model="filter.operator">
<ElOption v-for="item in operatorOptions" :key="item.value" :label="item.label" :value="item.value"/>
</ElSelect>
<input
v-model="filter.value"
type="text"
autocomplete="off"
:placeholder="filter.operator.indexOf('regexp') !== -1 ? 'regular expression' : ''"
/>
</template>

<a href="#" @click="removeFilter(index)" class="remove-filter" :title="text('Remove filter')"><span>{{ text('Delete') }}</span></a>

</li>
</ul>
</section>
</template>

<script>
import {find} from 'lodash'
export default {
data () {
return {
f: this.filters
}
},
props: {
fields: Array,
filters: Array,
operators: {
type: Object,
required: true
}
},
computed: {
operatorOptions () {
// provide operators in the format {value: '==', label: 'is'}
var arr = []
Object.keys(this.operators).map(key => {
arr.push({
value: key,
label: this.operators[key].label
})
})
return arr
},
optInUsed () {
return !!find(this.f, {type: 'opt-in'})
}
},
watch: {
f (val) {
this.$emit('update:filters', val)
},
filters (val) {
this.f = this.filters
}
},
methods: {
text (text) {
switch (text) {
case 'Add filter': return Drupal.t('Add filter')
case 'opt-in filter': return Drupal.t('Opt-in')
case 'submission-field filter': return Drupal.t('Submission field')
case 'If': return Drupal.t('If')
case 'and': return Drupal.t('and')
case 'supporter': return Drupal.t('supporter')
case 'has': return Drupal.t('has')
case 'has not': return Drupal.t('has not')
case 'opted in': return Drupal.t('opted in')
case 'regular expression': return Drupal.t('regular expression')
case 'type to browse values': return Drupal.t('type to browse values')
case 'Remove filter': return Drupal.t('Remove filter')
case 'Delete': return Drupal.t('Delete')
}
},
addFilter (type) {
var filter = {
id: null,
type
}
switch (type) {
case 'opt-in':
filter.value = true
break
case 'submission-field':
filter.field = this.fields[0].id
filter.operator = '=='
filter.value = ''
}
this.f.push(filter)
},
removeFilter (index) {
this.f.splice(index, 1)
}
}
}
</script>

<style lang="css">
</style>
Expand Up @@ -27,14 +27,13 @@
/>
<div v-if="showErrors && !destinationIsValid" class="pra-error-message">{{ text('destination error') }}</div>
</section>
<!--

<FilterEditor
:fields="targetAttributes"
:fields="filterFields"
:filters.sync="currentRedirect.filters"
:filter-default="{type: 'target-attribute'}"
:operators="OPERATORS"
/>
-->

<span slot="footer" :class="{'pra-dialog-footer': true, 'pra-dialog-alert': modalDirty}">
<span v-if="modalDirty" class="pra-dialog-alert-message">{{ text('unsaved changes') }}</span>
<el-button @click="cancelButtonHandler()" class="js-modal-cancel">{{ text('Cancel') }}</el-button>
Expand All @@ -50,10 +49,12 @@ import {OPERATORS, emptyRedirect} from '@/utils/defaults'
import {mapState} from 'vuex'
import {isEqual, omit} from 'lodash'
import DestinationField from './DestinationField'
import FilterEditor from './FilterEditor'
export default {
components: {
DestinationField
DestinationField,
FilterEditor
},
data () {
Expand Down Expand Up @@ -102,7 +103,8 @@ export default {
},
...mapState([
'redirects',
'currentRedirectIndex'
'currentRedirectIndex',
'filterFields'
])
},
Expand Down
16 changes: 15 additions & 1 deletion campaignion_wizard/redirects_app/src/store/state.js
Expand Up @@ -5,6 +5,20 @@ export function createState () {
redirects: [],
defaultRedirect: emptyRedirect(),
currentRedirectIndex: null, // the item in the redirects array that is currently edited or -1 for a new item
initialData: {}
initialData: {},
filterFields: [
{
id: 'f_name',
label: 'First name'
},
{
id: 'l_name',
label: 'Last name'
},
{
id: 'email',
label: 'Email address'
}
]
}
}
12 changes: 12 additions & 0 deletions campaignion_wizard/redirects_app/src/utils/defaults.js
Expand Up @@ -7,9 +7,21 @@ export const OPERATORS = {
label: Drupal.t('is not'),
phrase: Drupal.t('@attribute is not @value')
},
'contains': {
label: Drupal.t('contains'),
phrase: Drupal.t('@attribute contains @value')
},
'!contains': {
label: Drupal.t('does not contain'),
phrase: Drupal.t('@attribute doesn’t contain @value')
},
'regexp': {
label: Drupal.t('matches'),
phrase: Drupal.t('@attribute matches @value')
},
'!regexp': {
label: Drupal.t('does not match'),
phrase: Drupal.t('@attribute doesn’t match @value')
}
}

Expand Down

0 comments on commit ae57129

Please sign in to comment.