PluginProbe
Fluent Forms – Customizable Contact Forms, Survey, Quiz, & Conversational Form Builder / 3.6.61
Fluent Forms – Customizable Contact Forms, Survey, Quiz, & Conversational Form Builder v3.6.61
6.2.15 6.2.14 6.2.13 6.2.12 6.2.10 6.2.11 6.2.9 6.2.8 6.2.7 6.2.6 6.2.5 6.2.4 6.2.3 6.2.2 3.6.22 3.6.31 3.6.40 3.6.41 3.6.42 3.6.50 3.6.51 3.6.60 3.6.61 3.6.62 3.6.64 All 197 releases
fluentform / resources / assets / admin / views / Entry.vue

Entry.vue in Fluent Forms – Customizable Contact Forms, Survey, Quiz, & Conversational Form Builder 3.6.61, at resources/assets/admin/views/Entry.vue

399 lines 17.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <template>
2 <div class="fluentform-wrapper">
3 <div class="entry_header">
4 <router-link class="pull-right" :to="{ name: 'form-entries' }">
5 <el-button icon="el-icon-back" size="small">Back to Entries</el-button>
6 </router-link>
7
8 <el-button class="pull-right" size="small" @click="changeEntry('+')" :disabled="!nextId">
9 Next <i class="el-icon-arrow-right"/>
10 </el-button>
11 <el-button class="pull-right" size="small" @click="changeEntry('-')" :disabled="!prevId">
12 <i class="el-icon-arrow-left"/> Previous
13 </el-button>
14
15 <h3>Entry Details #{{entry.serial_number}}</h3>
16 </div>
17
18 <el-row v-loading="loading" :gutter="20" style="min-height: 260px;">
19 <el-col :xs="24" :sm="18" :md="18" :lg="18">
20 <div class="entry_info_box entry_input_data">
21 <div class="entry_info_header">
22 <div class="info_box_header">
23 <span @click="view_as_json = !view_as_json"
24 class="dashicons dashicons-editor-code json_action"></span>
25 Form Entry Data
26 </div>
27 <div class="info_box_header_actions">
28 <span @click="changeFavorite()"
29 title="Remove from Favorites" v-if="entry.is_favourite != '0' || entry.is_favourite == '1'"
30 class="el-icon-star-on star_big action_button"></span>
31 <span @click="changeFavorite()"
32 title="Mark as Favorite" v-else
33 class="el-icon-star-off star_big action_button"></span>
34
35 <el-checkbox true-label="yes" false-label="no" v-model="show_empty">Show empty fields</el-checkbox>
36 </div>
37 </div>
38 <div v-if="entry.serial_number" class="entry_info_body">
39 <div v-show="!view_as_json" class="wpf_entry_details">
40 <div v-for="(label, label_index) in labels"
41 :key="label_index"
42 v-show="show_empty == 'yes' || entry.user_inputs[label_index]"
43 class="wpf_each_entry">
44
45 <div class="wpf_entry_label">
46 {{label}}
47 </div>
48
49 <template v-if="formFields[label_index]['element'] == 'input_email'">
50 <div v-show="entry.user_inputs[label_index]" class="wpf_entry_value">
51 <a :href="'mailto:'+entry.user_inputs[label_index]">{{
52 entry.user_inputs[label_index] }}</a>
53 </div>
54 </template>
55 <template v-else-if="formFields[label_index]['element'] == 'input_file'">
56 <entry-file-list :itemKey="label_index" :dataItems="original_data"></entry-file-list>
57 </template>
58 <template
59 v-else-if="['input_image', 'signature'].indexOf(formFields[label_index]['element']) != -1">
60 <entry-image-list :itemKey="label_index" :dataItems="original_data"></entry-image-list>
61 </template>
62 <template
63 v-else-if="['input_checkbox', 'select'].indexOf(formFields[label_index]['element']) != -1">
64 <div
65 v-html="maybeExtractCommaArrayInfo(entry.user_inputs[label_index], formFields[label_index]['raw'])"></div>
66 </template>
67 <template v-else>
68 <div class="wpf_entry_value" v-html="entry.user_inputs[label_index]"></div>
69 </template>
70 </div>
71 </div>
72 <div v-show="view_as_json">
73 <textarea class="show_code" readonly>{{ prettifyJson(entry) }}</textarea>
74 </div>
75 </div>
76 </div>
77
78 <payment-summary @reload_payments="getEntry()" v-if="order_data" :submission="entry" :order_data="order_data"></payment-summary>
79
80 <entry_notes :entry_id="entry_id" :form_id="form_id"/>
81
82 <submission_logs :entry_id="entry_id" />
83
84 </el-col>
85 <el-col :xs="24" :sm="6" :md="6" :lg="6">
86 <div class="entry_info_box postbox">
87 <div class="entry_info_header">
88 <b>Submission Info</b>
89 </div>
90 <div class="entry_info_body narrow_items">
91 <div class="wpf_entry_details">
92 <div class="wpf_each_entry">
93 <p>Entity ID: #{{entry.id}}</p>
94 </div>
95 <div class="wpf_each_entry">
96 <p>User IP : <a target="_blank" rel="noopener" :href="'https://ipinfo.io/'+entry.ip">{{
97 entry.ip }}</a></p>
98 </div>
99 <div class="wpf_each_entry">
100 <p style="word-break: break-all;">Source URL : <a target="_blank" :href="entry.source_url">{{ entry.source_url }}</a>
101 </p>
102 </div>
103 <div class="wpf_each_entry">
104 <p>Browser : {{ entry.browser }}</p>
105 </div>
106 <div class="wpf_each_entry">
107 <p>Device : {{ entry.device }}</p>
108 </div>
109 <div class="wpf_each_entry">
110
111 <p v-if="entry.user">User : <a target="_blank" rel="noopener"
112 :href="entry.user.permalink">{{ entry.user.name }}</a>
113 </p>
114 <p v-else>User : Guest</p>
115 </div>
116 <div class="wpf_each_entry">
117 <p>Status : {{ entry_statuses[entry.status] || entry.status }}</p>
118 </div>
119 <div class="wpf_each_entry">
120 <p>Submitted On : {{ entry.created_at }}</p>
121 </div>
122 </div>
123 </div>
124 <div class="entry-footer">
125 <el-button @click="editTable = true" size="mini" type="primary" icon="el-icon-edit"> Edit
126 </el-button>
127
128 <el-dropdown @command="handleStatusChange" type="info">
129 <el-button size="mini" type="info">
130 Change status to <i class="el-icon-arrow-down el-icon--right"></i>
131 </el-button>
132 <el-dropdown-menu slot="dropdown">
133 <el-dropdown-item v-for="(statusName, statusKey) in entry_statuses" :command="statusKey" :key="statusKey">{{statusName}}</el-dropdown-item>
134 </el-dropdown-menu>
135 </el-dropdown>
136 </div>
137 </div>
138 <div v-for="(widget, widgetKey) in widgets" class="entry_info_box postbox">
139 <div class="entry_info_header">
140 <b>{{widget.title}}</b>
141 </div>
142 <div class="entry_info_body narrow_items">
143 <div v-html="widget.content"></div>
144 </div>
145 </div>
146
147 </el-col>
148 </el-row>
149
150 <email-resend :form_id="form_id" :entry_id="entry_id" />
151 <manual-entry-actions :form_id="form_id" :entry_id="entry_id" />
152 <el-dialog
153 title="Edit Entry Data"
154 top="42px"
155 :append-to-body="true"
156 :visible.sync="editTable"
157 width="60%">
158 <edit-entry @reloadData="getEntry()" :form_id="form_id" :entry_id="entry_id" @close="editTable = false"
159 v-if="editTable" :labels="labels" :submission="entry"
160 :fields="formFields"></edit-entry>
161 </el-dialog>
162 </div>
163 </template>
164
165 <script type="text/babel">
166 import remove from '../components/confirmRemove'
167 import entry_notes from './EntryNotes'
168 import submission_logs from './SubmissionLogs'
169 import editEntry from './EditEntry'
170 import each from 'lodash/each';
171 import EntryFileList from './Helpers/FilesList.vue';
172 import EntryImageList from './Helpers/ImageList.vue';
173 import EmailResend from './Helpers/_ResentEmailNotification'
174 import ManualEntryActions from './Helpers/_ManualEntryActions'
175 import PaymentSummary from './Payments/PaymentSummary'
176
177 export default {
178 name: 'Entry',
179 props: ['has_pdf'],
180 components: {
181 remove: remove,
182 entry_notes: entry_notes,
183 submission_logs,
184 editEntry,
185 EntryFileList,
186 EntryImageList,
187 EmailResend,
188 PaymentSummary,
189 ManualEntryActions
190 },
191 data() {
192 return {
193 loading: true,
194 editTable: false,
195 entry: false,
196 view_as_json: false,
197 entry_type: this.$route.query.type || 'all',
198 developer_mode: true,
199 form_id: window.fluent_form_entries_vars.form_id,
200 entry_id: this.$route.params.entry_id,
201 nextId: null,
202 prevId: null,
203 order_data: null,
204 sort_by: this.$route.query.sort_by,
205 paginate: {
206 total: null,
207 current_page: this.$route.query.current_page
208 },
209 entry_statuses: window.fluent_form_entries_vars.entry_statuses,
210 entry_position: this.$route.query.pos,
211 operator: null,
212 currentSerialNo: null,
213 formFields: {},
214 original_data: {},
215 show_empty: 'no',
216 widgets: {}
217 }
218 },
219 methods: {
220 getEntry() {
221 let data = {
222 action: 'fluentform-get-entry',
223 current_page: this.paginate.current_page,
224 form_id: this.form_id,
225 entry_id: this.entry_id,
226 entry_type: this.entry_type,
227 search: this.search_string,
228 sort_by: this.sort_by,
229 };
230 this.loading = true;
231 jQuery.get(ajaxurl, data)
232 .then((res) => {
233 if (res.data.submission && res.data.submission.id) {
234 this.entry = res.data.submission;
235 this.original_data = JSON.parse(res.data.submission.response);
236 this.labels = res.data.labels;
237 this.formFields = res.data.fields;
238 this.currentSerialNo = this.entry.myRowSerial;
239 this.entry_id = this.entry.id;
240 this.order_data = res.data.order_data;
241 this.widgets = res.data.widgets;
242
243 this.nextId = res.data.next && res.data.next.id;
244 this.prevId = res.data.prev && res.data.prev.id;
245
246 this.$router.push({
247 name: 'form-entry', params: {entry_id: this.entry.id},
248 query: this.$route.query
249 });
250
251 ffEntriesEvents.$emit(
252 'change-title',
253 `Entry ${ this.entry.serial_number || '' }`
254 );
255
256 } else {
257 this.$notify.warning({
258 message: 'No entry found.',
259 offset: 30
260 });
261 }
262 })
263 .fail((error) => {
264 console.log(error);
265 this.$notify.warning({
266 message: error.responseJSON.data.message,
267 offset: 30
268 });
269 })
270 .always(() => {
271 this.loading = false;
272 });
273 },
274 changeFavorite() {
275 let newStatus = this.entry.is_favourite;
276 if(newStatus == '0' || newStatus === 0) {
277 newStatus = 1;
278 } else {
279 newStatus = '0';
280 }
281
282 let data = {
283 action: 'fluentform-change-entry-favorites',
284 form_id: this.form_id,
285 entry_id: this.entry_id,
286 is_favourite: newStatus
287 };
288
289 jQuery.post(ajaxurl, data)
290 .then(response => {
291 this.entry.is_favourite = newStatus;
292 })
293 .fail(error => {
294 console.log(error);
295 });
296 },
297 handleStatusChange(status) {
298 let data = {
299 action: 'fluentform-change-entry-status',
300 form_id: this.form_id,
301 entry_id: this.entry_id,
302 status: status
303 };
304
305 jQuery.post(ajaxurl, data)
306 .then(response => {
307 this.entry.status = status;
308 this.$notify({
309 title: 'Success',
310 message: response.data.message,
311 type: 'success',
312 offset: 30
313 });
314 })
315 .fail(error => {
316 console.log(error);
317 });
318 },
319 changeEntry(operator) {
320 let entryId = (operator === '+' && this.nextId) || (operator === '-' && this.prevId);
321
322 if (entryId) {
323 this.entry_id = entryId;
324
325 this.getEntry();
326 }
327 },
328 explodeFileUrls(value, chunkSize = 4) {
329 return value ? _ff.chunk(value.split(', '), chunkSize) : [];
330 },
331 maybeExtractCommaArrayInfo(dataValue, field) {
332
333 if (typeof dataValue == 'string' && field.element == 'input_checkbox') {
334 return dataValue;
335 }
336
337 if(field.element == 'select' && field.attributes && !field.attributes.multiple) {
338 return dataValue;
339 }
340 if (!dataValue) {
341 return;
342 }
343
344 let itemArray = [];
345
346 if(typeof dataValue == 'string') {
347 itemArray = dataValue.split(',');
348 }
349
350
351 let options = field.options;
352
353 if(!options) {
354 let advancedOptions = field.settings.advanced_options;
355 if(advancedOptions) {
356 options = {};
357 each(advancedOptions, (optionItem) => {
358 options[optionItem.value] = optionItem.label;
359 });
360 }
361 }
362
363 if (!options) {
364 return dataValue;
365 }
366
367
368 if(itemArray.length == 1) {
369 return `<div class="wpf_entry_value">${options[dataValue] || dataValue}</div>`;
370 }
371
372 let itemHtml = '<ul class="entry_item_list">';
373 each(itemArray, (item) => {
374 item = item.trim();
375 itemHtml += `<li>${options[item] || item}</li>`;
376 });
377 itemHtml += '</ul>';
378 return itemHtml;
379 },
380 dataType(data) {
381 return typeof data;
382 },
383 prettifyJson(entry) {
384 let data = {
385 id: entry.id,
386 form_id: entry.form_id,
387 original: this.original_data,
388 formatted: entry.user_inputs
389 };
390
391 return JSON.stringify(data, null, 8);
392 }
393 },
394 mounted() {
395 this.getEntry();
396 }
397 };
398 </script>
399