/
RedirectDialog.vue
195 lines (183 loc) · 6.53 KB
/
RedirectDialog.vue
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
<template lang="html">
<ElDialog
:title="dialogTitle"
:visible="visible"
:close-on-click-modal="false"
size="large"
:before-close="dialogCancelHandler"
>
<section class="pra-redirect-label">
<label :for="'pra-redirect-label-' + _uid">{{ text('Redirect label') }} <small>{{ text('seen only by you') }}</small></label>
<input type="text" v-model="currentRedirect.label" class="field-input" :id="'pra-redirect-label-' + _uid">
</section>
<FilterEditor
:fields="$root.$options.settings.fields"
:filters.sync="currentRedirect.filters"
:operators="OPERATORS"
/>
<section class="pra-redirect-destination">
<label :for="'pra-redirect-destination-' + _uid">{{ text('Redirect destination') }} <small>{{ text('type a node title or ID or paste a URL') }}</small></label>
<DestinationField
:id="'pra-redirect-destination-' + _uid"
:class="{'pra-has-error': showErrors && !destinationIsValid}"
:value="destination"
:placeholder="text('Type to search nodes')"
:show-dropdown-on-focus="true"
data-key="values"
label-key="label"
:url="$root.$options.settings.endpoints.nodes"
:headers="{}"
search-param="s"
:count="20"
@input="item => {destination = item}"
/>
<div v-if="showErrors && !destinationIsValid" class="pra-error-message">{{ text('destination error') }}</div>
</section>
<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>
<el-button type="primary" :disabled="currentRedirectIsEmpty" @click="updateRedirect" class="js-modal-save">{{ text('Done') }}</el-button>
</span>
</ElDialog>
</template>
<script>
import {clone, validateDestination} from '@/utils'
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,
FilterEditor
},
data () {
return {
currentRedirect: emptyRedirect(),
modalDirty: false,
showErrors: false,
OPERATORS
}
},
computed: {
dialogTitle () {
if (this.currentRedirectIndex === -1) {
return Drupal.t('Add personalized redirect')
} else if (this.currentRedirectIndex >= 0) {
if (this.currentRedirect.label) {
return Drupal.t('Edit @itemName', {'@itemName': this.currentRedirect.label})
} else {
return Drupal.t('Edit personalized redirect')
}
}
},
currentRedirectIsEmpty () {
return this.currentRedirectIndex !== null && isEqual(omit(this.currentRedirect, ['id', 'prettyDestination']), omit(emptyRedirect(), ['id', 'prettyDestination']))
},
visible () {
return this.currentRedirectIndex !== null
},
destination: {
// destination and prettyDestination translated for the DestinationField
// component as value and label
get () {
return {
value: this.currentRedirect.destination,
label: this.currentRedirect.prettyDestination
}
},
set (val) {
this.currentRedirect.destination = val.value
this.currentRedirect.prettyDestination = val.label
}
},
destinationIsValid () {
return validateDestination(this.currentRedirect.destination)
},
...mapState([
'redirects',
'currentRedirectIndex'
])
},
methods: {
text (text) {
switch (text) {
case 'Redirect label': return Drupal.t('Redirect label')
case 'seen only by you': return Drupal.t('(seen only by you)')
case 'Redirect destination': return Drupal.t('Redirect destination')
case 'type a node title or ID or paste a URL': return Drupal.t('type a node title or ID or paste a URL')
case 'Type to search nodes': return Drupal.t('Type to search nodes')
case 'destination error': return Drupal.t('Please enter a valid URL or choose a node.')
case 'unsaved changes': return Drupal.t('You have unsaved changes!')
case 'Cancel': return this.modalDirty ? Drupal.t('Discard my changes') : Drupal.t('Cancel')
case 'Done': return Drupal.t('Done')
}
},
tryClose (options) {
// Any changes?
if (this.currentRedirectIndex !== -1 && isEqual(this.currentRedirect, this.redirects[this.currentRedirectIndex]) ||
this.currentRedirectIndex === -1 && this.currentRedirectIsEmpty ||
(this.modalDirty && options && options.button === 'cancel')) {
// No changes or force close via cancel button: allow to close modal.
return true
} else {
// There are unsaved changes, alert!
this.modalDirty = true
return false
}
},
dialogCancelHandler (done) {
if (this.tryClose()) {
this.close()
done()
}
},
cancelButtonHandler () {
if (this.tryClose({button: 'cancel'})) {
this.close()
}
},
updateRedirect () {
if (!this.destinationIsValid) {
this.showErrors = true
return
}
this.$store.commit({type: 'updateRedirect', redirect: this.currentRedirect})
this.close()
},
close () {
this.modalDirty = false
this.showErrors = false
this.$store.commit('leaveRedirect')
this.$root.$emit('closeRedirectDialog')
}
},
mounted () {
this.$root.$on('newRedirect', () => {
this.currentRedirect = emptyRedirect()
this.$store.commit('editNewRedirect')
})
this.$root.$on('editRedirect', index => {
this.currentRedirect = clone(this.redirects[index])
this.$store.commit({type: 'editRedirect', index})
})
this.$root.$on('duplicateRedirect', index => {
const duplicate = clone(this.redirects[index])
duplicate.id = emptyRedirect().id
duplicate.label = Drupal.t('Copy of @redirectLabel', {'@redirectLabel': duplicate.label})
this.currentRedirect = duplicate
this.$store.commit('editNewRedirect')
})
document.addEventListener('keyup', e => {
// Catch Enter key and save redirect.
if (this.visible && !this.currentRedirectIsEmpty && e.keyCode === 13 && document.activeElement.tagName.toLowerCase() !== 'textarea') {
e.preventDefault()
this.updateRedirect()
}
})
}
}
</script>
<style lang="css">
</style>