473 lines
30 KiB
JavaScript
473 lines
30 KiB
JavaScript
(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
|
|
"use strict";
|
|
|
|
const Repeater = (window.Swal && typeof window.Swal.mixin === 'function')
|
|
? window.Swal.mixin({
|
|
customClass: {
|
|
container: 'wpcfto-settings',
|
|
confirmButton: 'button'
|
|
}
|
|
})
|
|
: {
|
|
// Fallback that mimics Swal.fire returning a Promise
|
|
fire: (opts) => Promise.resolve({
|
|
isConfirmed: window.confirm((opts && (opts.text || opts.html || opts.title)) || 'Are you sure?')
|
|
})
|
|
};
|
|
|
|
Vue.component('wpcfto_repeater', {
|
|
mixins: (window.validationMixin ? [window.validationMixin] : []),
|
|
props: ['fields', 'field_label', 'field_name', 'field_id', 'field_value'],
|
|
data: function data() {
|
|
return {
|
|
repeater: [],
|
|
repeater_values: {}
|
|
};
|
|
},
|
|
template: `
|
|
<div class="wpcfto_generic_field wpcfto_generic_field_repeater wpcfto-repeater unflex_fields">
|
|
<wpcfto_fields_aside_before
|
|
:fields="fields"
|
|
:field_label="field_label"
|
|
:required="fields && fields.required === true"
|
|
/>
|
|
<div class="wpcfto-field-content">
|
|
<!-- Required proxy: forces validation when repeater is empty -->
|
|
<input
|
|
v-if="fields && fields.required === true"
|
|
class="wpcfto-required-proxy"
|
|
type="text"
|
|
:name="field_id + '__required__'"
|
|
:value="(repeater && repeater.length ? 'ok' : '')"
|
|
:required="!repeater || repeater.length === 0"
|
|
:disabled="repeater && repeater.length > 0"
|
|
tabindex="-1" readonly
|
|
style="position:absolute; left:-9999px; top:auto; width:1px; height:1px; opacity:0; pointer-events:none;"
|
|
/>
|
|
<!-- Hidden data carrier to persist repeater rows via standard form submit -->
|
|
<input
|
|
type="hidden"
|
|
:name="field_name"
|
|
:value="jsonValue"
|
|
/>
|
|
<div v-for="(area, area_key) in repeater" class="wpcfto-repeater-single" :class="'wpcfto-repeater_' + field_name + '_' + area_key">
|
|
<div class="wpcfto_group_title" @click="toggleArea(area)" v-html="getGroupTitle(area, area_key)"></div>
|
|
<div class="repeater_inner" :class="{ closed: area.closed_tab }">
|
|
<div class="wpcfto-repeater-field" v-for="(field, field_name_inner) in fields.fields">
|
|
<component
|
|
:is="'wpcfto_' + field.type"
|
|
:fields="field"
|
|
:field_id="field.field_id + '_' + area_key + '_' + field_name_inner"
|
|
:field_name="field_name + '_' + area_key + '_' + field_name_inner"
|
|
:field_label="field.label"
|
|
:field_value="getFieldValue(area_key, field, field_name_inner)"
|
|
:field_data="field"
|
|
:field_native_name="field_name"
|
|
:field_native_name_inner="field_name_inner"
|
|
@wpcfto-get-value="$set(repeater[area_key], field_name_inner, $event)"
|
|
:ref="'field_' + area_key + '_' + field_name_inner"
|
|
></component>
|
|
</div>
|
|
</div>
|
|
<span class="wpcfto-repeater-single-delete" @click="removeArea(area_key)">
|
|
<i class="fa fa-trash-alt"></i>Delete
|
|
</span>
|
|
</div>
|
|
<div v-if="repeater && repeater.length > 0" class="separator"></div>
|
|
<div class="addArea" @click="validateAndAddArea">
|
|
<i class="fa fa-plus-circle"></i>
|
|
<span v-html="'Add ' + field_label"></span>
|
|
</div>
|
|
</div>
|
|
<wpcfto_fields_aside_after :fields="fields"></wpcfto_fields_aside_after>
|
|
</div>
|
|
`,
|
|
mounted: function mounted() {
|
|
var _this = this;
|
|
if (typeof _this.field_value === 'string' && WpcftoIsJsonString(_this.field_value)) {
|
|
_this.field_value = JSON.parse(_this.field_value);
|
|
}
|
|
if (typeof _this.field_value !== 'undefined' && typeof _this.field_value !== 'string') {
|
|
_this.$set(_this, 'repeater_values', _this.field_value);
|
|
_this.repeater_values.forEach(function(item, index) {
|
|
var repeaterItem = { closed_tab: true };
|
|
for (var field_name in item) {
|
|
repeaterItem[field_name] = item[field_name];
|
|
}
|
|
_this.repeater.push(repeaterItem);
|
|
});
|
|
// *** Ensure ALL rows are closed after initialization ***
|
|
_this.repeater.forEach(function(item) {
|
|
item.closed_tab = true;
|
|
});
|
|
}
|
|
// Normalize rows to include only declared fields (copy defaults if missing)
|
|
if (this.fields && this.fields.fields) {
|
|
this.repeater = this.repeater.map((row) => {
|
|
const normalized = { closed_tab: true };
|
|
Object.keys(this.fields.fields).forEach((fname) => {
|
|
if (typeof row[fname] !== 'undefined') {
|
|
normalized[fname] = row[fname];
|
|
} else {
|
|
const def = this.fields.fields[fname] && this.fields.fields[fname].value;
|
|
if (typeof def !== 'undefined') normalized[fname] = def;
|
|
}
|
|
});
|
|
return normalized;
|
|
});
|
|
}
|
|
// Initial validation state
|
|
if (typeof this.validateField === 'function') this.validateField();
|
|
if (this.fields && this.fields.required === true) {
|
|
// Block Save when repeater is required but empty (length check only)
|
|
const handler = (e) => {
|
|
// Only enforce when this component is in DOM
|
|
if (!this.$el || !document.body.contains(this.$el)) return;
|
|
const emptyRequired = !this.repeater || this.repeater.length === 0;
|
|
if (emptyRequired) {
|
|
e.preventDefault();
|
|
e.stopPropagation();
|
|
this.focusSelf();
|
|
}
|
|
};
|
|
try {
|
|
const btns = document.querySelectorAll('.wpcfto_save_settings, .wpcfto_save_metabox');
|
|
btns.forEach(btn => btn.addEventListener('click', handler, true));
|
|
this.__wpcftoSaveHandler = handler;
|
|
} catch(e) {}
|
|
// Also prevent <form> submission if invalid (works for both settings + metabox)
|
|
try {
|
|
const form = this.$el.closest('form');
|
|
if (form) {
|
|
const onSubmit = (e) => {
|
|
const emptyRequired = !this.repeater || this.repeater.length === 0;
|
|
if (emptyRequired) {
|
|
e.preventDefault();
|
|
e.stopPropagation();
|
|
this.focusSelf();
|
|
}
|
|
};
|
|
form.addEventListener('submit', onSubmit, true);
|
|
this.__wpcftoFormSubmitHandler = onSubmit;
|
|
}
|
|
} catch(e) {}
|
|
}
|
|
if (typeof this.validateField === 'function') this.validateField();
|
|
},
|
|
beforeDestroy: function () {
|
|
if (this.__wpcftoSaveHandler) {
|
|
try {
|
|
const btns = document.querySelectorAll('.wpcfto_save_settings, .wpcfto_save_metabox');
|
|
btns.forEach(btn => btn.removeEventListener('click', this.__wpcftoSaveHandler, true));
|
|
} catch(e) {}
|
|
this.__wpcftoSaveHandler = null;
|
|
}
|
|
if (this.__wpcftoFormSubmitHandler) {
|
|
try {
|
|
const form = this.$el && this.$el.closest ? this.$el.closest('form') : null;
|
|
if (form) form.removeEventListener('submit', this.__wpcftoFormSubmitHandler, true);
|
|
} catch(e) {}
|
|
this.__wpcftoFormSubmitHandler = null;
|
|
}
|
|
},
|
|
methods: {
|
|
focusSelf() {
|
|
try {
|
|
const rect = this.$el.getBoundingClientRect();
|
|
const top = window.pageYOffset + rect.top - 60;
|
|
window.scrollTo({ top, behavior: 'smooth' });
|
|
} catch(e) {}
|
|
try { this.$el.classList.add('wpcfto-invalid'); } catch(e) {}
|
|
},
|
|
// scrollIntoViewIfNeeded() {
|
|
// try {
|
|
// const top = window.pageYOffset + this.$el.getBoundingClientRect().top - 60;
|
|
// window.scrollTo({ top, behavior: 'smooth' });
|
|
// } catch(e) {}
|
|
// },
|
|
formatLabelPath(parts) {
|
|
return parts.filter(Boolean).map(function (s) {
|
|
return String(s).trim();
|
|
}).filter(Boolean).join(' → ');
|
|
},
|
|
validateField() {
|
|
// If this repeater is not required, always treat as valid and clean any invalid markers
|
|
if (!(this.fields && this.fields.required === true)) {
|
|
try { this.$el.classList.remove('wpcfto-invalid'); } catch(e){}
|
|
try { this.$el.removeAttribute('aria-invalid'); } catch(e){}
|
|
try {
|
|
const fid = this.field_id || (this.fields && this.fields.field_id);
|
|
if (fid) this.$root.$emit('field-validation', { fieldId: fid, isValid: true });
|
|
} catch(e) {}
|
|
return true;
|
|
}
|
|
// Repeater-level required: valid iff it has at least one row
|
|
let isValid = true;
|
|
if (this.fields && this.fields.required === true) {
|
|
const len = (this.repeater && Array.isArray(this.repeater)) ? this.repeater.length : 0;
|
|
isValid = len > 0;
|
|
}
|
|
|
|
if (!isValid) {
|
|
try { this.$el.classList.add('wpcfto-invalid'); } catch(e){}
|
|
try { this.$el.setAttribute('aria-invalid','true'); } catch(e){}
|
|
// Notify global validator (validationMixin listener)
|
|
try {
|
|
const fid = this.field_id || (this.fields && this.fields.field_id);
|
|
if (fid) this.$root.$emit('field-validation', { fieldId: fid, isValid: false });
|
|
} catch(e) {}
|
|
return false;
|
|
}
|
|
|
|
// valid state
|
|
try { this.$el.classList.remove('wpcfto-invalid'); } catch(e){}
|
|
try { this.$el.removeAttribute('aria-invalid'); } catch(e){}
|
|
try {
|
|
const fid = this.field_id || (this.fields && this.fields.field_id);
|
|
if (fid) this.$root.$emit('field-validation', { fieldId: fid, isValid: true });
|
|
} catch(e) {}
|
|
return true;
|
|
},
|
|
// This method validates all visible required fields in all rows before adding a new row
|
|
validateAndAddArea: function() {
|
|
const fieldsInRepeater = this._props.fields.fields;
|
|
let group_title = null;
|
|
Object.values(fieldsInRepeater).forEach(field => {
|
|
if ('is_group_title' in field) {
|
|
if (field.is_group_title !== false) {
|
|
group_title = field.label;
|
|
}
|
|
}
|
|
});
|
|
var invalidFields = [];
|
|
// Loop through all repeater rows and all fields
|
|
this.repeater.forEach((area, area_key) => {
|
|
for (const field_name_inner in this.fields.fields) {
|
|
const field = this.fields.fields[field_name_inner];
|
|
// Find the child component via $refs
|
|
const refName = 'field_' + area_key + '_' + field_name_inner;
|
|
const child = this.$refs[refName];
|
|
// $refs[refName] can be an array if used inside v-for, so get the first element
|
|
const childComponent = Array.isArray(child) ? child[0] : child;
|
|
// If the child component exists and has validateField method, call it
|
|
if (childComponent && typeof childComponent.validateField === 'function') {
|
|
// Only validate visible required fields
|
|
if (childComponent.isVisible && childComponent.fields && childComponent.fields.required) {
|
|
if (!childComponent.validateField()) {
|
|
invalidFields.push({
|
|
repeater_label: this._props.field_label,
|
|
group_title: group_title,
|
|
label: childComponent.fields.label || field_name_inner,
|
|
area: area_key + 1
|
|
});
|
|
// Optionally, you can add a visual error class here
|
|
// childComponent.$el.classList.add('invalid-field');
|
|
}
|
|
}
|
|
}
|
|
}
|
|
});
|
|
if (invalidFields.length > 0) {
|
|
// Compose error message
|
|
var msg = 'Please fill all required fields before adding a new item:\n\n';
|
|
const firstInvalidItem = invalidFields[0];
|
|
msg += 'Check item #'+firstInvalidItem.area+': <b>'+this.formatLabelPath([firstInvalidItem.group_title, firstInvalidItem.label])+'</b>';
|
|
// Use SweetAlert2 if available, otherwise alert()
|
|
if (typeof window.Swal === 'function') {
|
|
Repeater.fire({
|
|
icon: 'warning',
|
|
title: 'Required fields missing',
|
|
html: msg.replace(/\n/g, '<br>'),
|
|
width: 'fit-content',
|
|
customClass: {
|
|
confirmButton: 'btn text-bg-primary'
|
|
},
|
|
});
|
|
} else {
|
|
alert(msg);
|
|
}
|
|
return;
|
|
}
|
|
// If all required fields are valid, add a new row
|
|
this.addArea();
|
|
},
|
|
addArea: function addArea() {
|
|
// Close all rows before adding new
|
|
this.repeater.forEach(item => { item.closed_tab = true; });
|
|
this.repeater.push({ closed_tab: false }); // new row is open
|
|
var el = 'wpcfto-repeater_' + this.field_name + '_' + (this.repeater.length - 1);
|
|
Vue.nextTick(function () {
|
|
if (typeof jQuery !== 'undefined') {
|
|
var $ = jQuery;
|
|
$([document.documentElement, document.body]).animate({
|
|
scrollTop: $("." + el).offset().top - 40
|
|
}, 400);
|
|
}
|
|
});
|
|
this.validateField();
|
|
if (typeof jQuery !== 'undefined') {
|
|
jQuery(document).trigger('repeater-item-added', [this._props]);
|
|
}
|
|
},
|
|
toggleArea: function toggleArea(area) {
|
|
// Close all other rows
|
|
this.repeater.forEach(item => {
|
|
if (item !== area) {
|
|
this.$set(item, 'closed_tab', true);
|
|
}
|
|
});
|
|
|
|
// Toggle clicked row's closed_tab state
|
|
const isCurrentlyClosed = area.closed_tab === true || typeof area.closed_tab === 'undefined';
|
|
this.$set(area, 'closed_tab', !isCurrentlyClosed);
|
|
},
|
|
removeArea: function removeArea(areaIndex) {
|
|
// if (confirm('Do your really want to delete this field?')) {
|
|
// this.repeater.splice(areaIndex, 1);
|
|
// }
|
|
Repeater.fire({
|
|
icon: 'question',
|
|
html: 'Do your really want to delete this item?',
|
|
showCancelButton: true,
|
|
reverseButtons: true
|
|
}).then((result) => {
|
|
if (result.isConfirmed) {
|
|
this.repeater.splice(areaIndex, 1);
|
|
// jQuery action hook trigger example:
|
|
if (typeof jQuery !== 'undefined') {
|
|
jQuery(document).trigger('repeater-item-removed', [this._props, areaIndex]);
|
|
}
|
|
}
|
|
});
|
|
},
|
|
getFieldValue: function getFieldValue(key, field, field_name) {
|
|
if (this.repeater[key] && typeof this.repeater[key][field_name] !== 'undefined') {
|
|
return this.repeater[key][field_name];
|
|
}
|
|
if (typeof this.repeater_values !== 'undefined' &&
|
|
typeof this.repeater_values[key] !== 'undefined' &&
|
|
typeof this.repeater_values[key][field_name] !== 'undefined') {
|
|
return this.repeater_values[key][field_name];
|
|
}
|
|
return field.value;
|
|
},
|
|
getGroupTitle(area, area_key) {
|
|
let groupTitleFieldName = null;
|
|
let groupTitleField = null;
|
|
for (const [fname, field] of Object.entries(this.fields.fields)) {
|
|
if (field.is_group_title) {
|
|
groupTitleFieldName = fname;
|
|
groupTitleField = field;
|
|
break;
|
|
}
|
|
}
|
|
if (groupTitleFieldName) {
|
|
let value = area[groupTitleFieldName];
|
|
if (typeof value === 'undefined' && this.repeater_values && this.repeater_values[area_key]) {
|
|
value = this.repeater_values[area_key][groupTitleFieldName];
|
|
}
|
|
if (typeof value === 'undefined' || value === '') {
|
|
value = groupTitleField.label || this.field_label;
|
|
} else {
|
|
if (groupTitleField.options && groupTitleField.options[value]) {
|
|
value = groupTitleField.options[value];
|
|
}
|
|
}
|
|
return value;
|
|
}
|
|
return this.field_label + ' #' + (area_key + 1);
|
|
},
|
|
validateAllRows() {
|
|
let invalidFields = [];
|
|
|
|
this.repeater.forEach((area, area_key) => {
|
|
for (const field_name_inner in this.fields.fields) {
|
|
const field = this.fields.fields[field_name_inner];
|
|
// Find child component by ref
|
|
const refName = 'field_' + area_key + '_' + field_name_inner;
|
|
const child = this.$refs[refName];
|
|
const childComponent = Array.isArray(child) ? child[0] : child;
|
|
|
|
if (childComponent && typeof childComponent.validateField === 'function') {
|
|
if (childComponent.isVisible && field.required) {
|
|
if (!childComponent.validateField()) {
|
|
invalidFields.push({
|
|
label: field.label || field_name_inner,
|
|
row: area_key + 1
|
|
});
|
|
// Optionally add visual error here
|
|
}
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
if (invalidFields.length > 0) {
|
|
let msg = 'Please fill all required fields before saving:\n\n';
|
|
msg += invalidFields.map(f => `Row #${f.row}: ${f.label}`).join('\n');
|
|
|
|
if (typeof window.Swal === 'function') {
|
|
Swal.fire({
|
|
icon: 'warning',
|
|
title: 'Required fields missing',
|
|
html: msg.replace(/\n/g, '<br>')
|
|
});
|
|
} else {
|
|
alert(msg);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
},
|
|
saveChanges() {
|
|
// Block if repeater required but empty OR if any child invalid
|
|
const selfValid = this.validateField();
|
|
// const rowsValid = this.validateAllRows();
|
|
if (!selfValid) { return; }
|
|
// Proceed with save logic here...
|
|
}
|
|
},
|
|
watch: {
|
|
repeater: {
|
|
deep: true,
|
|
handler: function handler(repeater) {
|
|
// Build a clean payload with only declared inner fields
|
|
const payload = (Array.isArray(repeater) ? repeater : []).map((row) => {
|
|
const out = {};
|
|
if (this.fields && this.fields.fields) {
|
|
Object.keys(this.fields.fields).forEach((fname) => {
|
|
if (typeof row[fname] !== 'undefined') out[fname] = row[fname];
|
|
});
|
|
}
|
|
return out;
|
|
});
|
|
this.$emit('wpcfto-get-value', payload);
|
|
this.validateField();
|
|
}
|
|
}
|
|
},
|
|
computed: {
|
|
jsonValue() {
|
|
const list = Array.isArray(this.repeater) ? this.repeater : [];
|
|
const fieldsDef = (this.fields && this.fields.fields) ? this.fields.fields : null;
|
|
const payload = list.map((row) => {
|
|
const out = {};
|
|
if (fieldsDef) {
|
|
Object.keys(fieldsDef).forEach((fname) => {
|
|
if (typeof row[fname] !== 'undefined') out[fname] = row[fname];
|
|
else {
|
|
const def = fieldsDef[fname] && fieldsDef[fname].value;
|
|
if (typeof def !== 'undefined') out[fname] = def;
|
|
}
|
|
});
|
|
}
|
|
return out;
|
|
});
|
|
try { return JSON.stringify(payload); } catch(e) { return '[]'; }
|
|
}
|
|
}
|
|
});
|
|
|
|
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImZha2VfM2EyMmQ1YTQuanMiXSwibmFtZXMiOlsiVnVlIiwiY29tcG9uZW50IiwicHJvcHMiLCJkYXRhIiwicmVwZWF0ZXIiLCJyZXBlYXRlcl92YWx1ZXMiLCJ0ZW1wbGF0ZSIsIm1vdW50ZWQiLCJfdGhpcyIsImZpZWxkX3ZhbHVlIiwiV3BjZnRvSXNKc29uU3RyaW5nIiwiSlNPTiIsInBhcnNlIiwiJHNldCIsImZvckVhY2giLCJwdXNoIiwibWV0aG9kcyIsImFkZEFyZWEiLCJjbG9zZWRfdGFiIiwiZWwiLCJmaWVsZF9uYW1lIiwibGVuZ3RoIiwibmV4dFRpY2siLCJqUXVlcnkiLCIkIiwiZG9jdW1lbnQiLCJkb2N1bWVudEVsZW1lbnQiLCJib2R5IiwiYW5pbWF0ZSIsInNjcm9sbFRvcCIsIm9mZnNldCIsInRvcCIsInRvZ2dsZUFyZWEiLCJhcmVhIiwiY3VycmVudFN0YXRlIiwicmVtb3ZlQXJlYSIsImFyZWFJbmRleCIsImNvbmZpcm0iLCJzcGxpY2UiLCJnZXRGaWVsZFZhbHVlIiwia2V5IiwiZmllbGQiLCJ2YWx1ZSIsIndhdGNoIiwiZGVlcCIsImhhbmRsZXIiLCIkZW1pdCJdLCJtYXBwaW5ncyI6IkFBQUE7O0FBRUFBLEdBQUcsQ0FBQ0MsU0FBSixDQUFjLGlCQUFkLEVBQWlDO0FBQy9CQyxFQUFBQSxLQUFLLEVBQUUsQ0FBQyxRQUFELEVBQVcsYUFBWCxFQUEwQixZQUExQixFQUF3QyxVQUF4QyxFQUFvRCxhQUFwRCxDQUR3QjtBQUUvQkMsRUFBQUEsSUFBSSxFQUFFLFNBQVNBLElBQVQsR0FBZ0I7QUFDcEIsV0FBTztBQUNMQyxNQUFBQSxRQUFRLEVBQUUsRUFETDtBQUVMQyxNQUFBQSxlQUFlLEVBQUU7QUFGWixLQUFQO0FBSUQsR0FQOEI7QUFRL0JDLEVBQUFBLFFBQVEsRUFBRSxtcEVBUnFCO0FBUy9CQyxFQUFBQSxPQUFPLEVBQUUsU0FBU0EsT0FBVCxHQUFtQjtBQUMxQixRQUFJQyxLQUFLLEdBQUcsSUFBWjs7QUFFQSxRQUFJLE9B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Q0FBUDtBQUNEO0FBN0JNLEdBeEJzQjtBQXVEL0J1QixFQUFBQSxLQUFLLEVBQUU7QUFDTHZDLElBQUFBLFFBQVEsRUFBRTtBQUNSd0MsTUFBQUEsSUFBSSxFQUFFLElBREU7QUFFUkMsTUFBQUEsT0FBTyxFQUFFLFNBQVNBLE9BQVQsQ0FBaUJ6QyxRQUFqQixFQUEyQjtBQUNsQyxhQUFLMEMsS0FBTCxDQUFXLGtCQUFYLEVBQStCMUMsUUFBL0I7QUFDRDtBQUpPO0FBREw7QUF2RHdCLENBQWpDIiwic291cmNlc0NvbnRlbnQiOlsiXCJ1c2Ugc3RyaWN0XCI7XG5cblZ1ZS5jb21wb25lbnQoJ3dwY2Z0b19yZXBlYXRlcicsIHtcbiAgcHJvcHM6IFsnZmllbGRzJywgJ2ZpZWxkX2xhYmVsJywgJ2ZpZWxkX25hbWUnLCAnZmllbGRfaWQnLCAnZmllbGRfdmFsdWUnXSxcbiAgZGF0YTogZnVuY3Rpb24gZGF0YSgpIHtcbiAgICByZXR1cm4ge1xuICAgICAgcmVwZWF0ZXI6IFtdLFxuICAgICAgcmVwZWF0ZXJfdmFsdWVzOiB7fVxuICAgIH07XG4gIH0sXG4gIHRlbXBsYXRlOiBcIlxcbiAgICA8ZGl2IGNsYXNzPVxcXCJ3cGNmdG9fZ2VuZXJpY19maWVsZCB3cGNmdG9fZ2VuZXJpY19maWVsZF9yZXBlYXRlciB3cGNmdG8tcmVwZWF0ZXIgdW5mbGV4X2ZpZWxkc1xcXCI+XFxuXFxuICAgICAgICA8d3BjZnRvX2ZpZWxkc19hc2lkZV9iZWZvcmUgOmZpZWxkcz1cXFwiZmllbGRzXFxcIiA6ZmllbGRfbGFiZWw9XFxcImZpZWxkX2xhYmVsXFxcIj48L3dwY2Z0b19maWVsZHNfYXNpZGVfYmVmb3JlPlxcbiAgICAgICAgXFxuICAgICAgICA8ZGl2IGNsYXNzPVxcXCJ3cGNmdG8tZmllbGQtY29udGVudFxcXCI+XFxuXFxuICAgICAgICAgICAgPGRpdiB2LWZvcj1cXFwiKGFyZWEsIGFyZWFfa2V5KSBpbiByZXBlYXRlclxcXCIgY2xhc3M9XFxcIndwY2Z0by1yZXBlYXRlci1zaW5nbGVcXFwiIDpjbGFzcz1cXFwiJ3dwY2Z0by1yZXBlYXRlcl8nICsgZmllbGRfbmFtZSArICdfJyArIGFyZWFfa2V5IFxcXCI+XFxuICAgIFxcbiAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVxcXCJ3cGNmdG9fZ3JvdXBfdGl0bGVcXFwiIHYtaHRtbD1cXFwiZmllbGRfbGFiZWwgKyAnICMnICsgKGFyZWFfa2V5ICsgMSlcXFwiPjwvZGl2PlxcbiAgICBcXG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cXFwicmVwZWF0ZXJfaW5uZXJcXFwiPlxcbiAgICBcXG4gICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XFxcIndwY2Z0by1yZXBlYXRlci1maWVsZFxcXCIgdi1mb3I9XFxcIihmaWVsZCwgZmllbGRfbmFtZV9pbm5lcikgaW4gZmllbGRzLmZpZWxkc1xcXCI+XFxuICAgICAgICAgICAgICAgICAgICBcXG4gICAgICAgICAgICAgICAgICAgICAgICA8Y29tcG9uZW50IDppcz1cXFwiJ3dwY2Z0b18nICsgZmllbGQudHlwZVxcXCJcXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDpmaWVsZHM9XFxcImZpZWxkXFxcIlxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgOmZpZWxkX25hbWU9XFxcImZpZWxkX25hbWUgKyAnXycgKyBhcmVhX2tleSArICdfJyArIGZpZWxkX25hbWVfaW5uZXJcXFwiXFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA6ZmllbGRfbGFiZWw9XFxcImZpZWxkLmxhYmVsXFxcIlxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgOmZpZWxkX3ZhbHVlPVxcXCJnZXRGaWVsZFZhbHVlKGFyZWFfa2V5LCBmaWVsZCwgZmllbGRfbmFtZV9pbm5lcilcXFwiXFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA6ZmllbGRfZGF0YT1cXFwiZmllbGRcXFwiXFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA6ZmllbGRfbmF0aXZlX25hbWU9XFxcImZpZWxkX25hbWVcXFwiXFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA6ZmllbGRfbmF0aXZlX25hbWVfaW5uZXI9XFxcImZpZWxkX25hbWVfaW5uZXJcXFwiXFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBAd3BjZnRvLWdldC12YWx1ZT1cXFwiJHNldChyZXBlYXRlclthcmVhX2tleV0sIGZpZWxkX25hbWVfaW5uZXIsICRldmVudClcXFwiPlxcbiAgICAgICAgICAgICAgICAgICAgICAgIDwvY29tcG9uZW50PlxcbiAgICBcXG4gICAgICAgICAgICAgICAgICAgIDwvZGl2PlxcbiAgICBcXG4gICAgICAgICAgICAgICAgPC9kaXY+XFxuICAgIFxcbiAgICAgICAgICAgICAgICA8c3BhbiBjbGFzcz1cXFwid3BjZnRvLXJlcGVhdGVyLXNpbmdsZS1kZWxldGVcXFwiIEBjbGljaz1cXFwicmVtb3ZlQXJlYShhcmVhX2tleSlcXFwiPlxcbiAgICAgICAgICAgICAgICAgICAgPGkgY2xhc3M9XFxcImZhIGZhLXRyYXNoLWFsdFxcXCI+PC9pPkRlbGV0ZVxcbiAgICAgICAgICAgICAgICA8L3NwYW4+XFxuICAgIFxcbiAgICAgICAgICAgIDwvZGl2PlxcbiAgICBcXG4gICAgICAgICAgICA8ZGl2IHYtaWY9XFxcInJlcGVhdGVyICYmIHJlcGVhdGVyLmxlbmd0aCA+IDBcXFwiIGNsYXNzPVxcXCJzZXBhcmF0b3JcXFwiPjwvZGl2PlxcbiAgICBcXG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVxcXCJhZGRBcmVhXFxcIiBAY2xpY2s9XFxcImFkZEFyZWFcXFwiPlxcbiAgICAgICAgICAgICAgICA8aSBjbGFzcz1cXFwiZmEgZmEtcGx1cy1jaXJjbGVcXFwiPjwvaT5cXG4gICAgICAgICAgICAgICAgPHNwYW4gdi1odG1sPVxcXCInQWRkICcgKyBmaWVsZF9sYWJlbFxcXCI+PC9zcGFuPlxcbiAgICAgICAgICAgIDwvZGl2PlxcbiAgICAgICAgXFxuICAgICAgICA8L2Rpdj5cXG4gICAgICAgIFxcbiAgICAgICAgPHdwY2Z0b19maWVsZHNfYXNpZGVfYWZ0ZXIgOmZpZWxkcz1cXFwiZmllbGRzXFxcIj48L3dwY2Z0b19maWVsZHNfYXNpZGVfYWZ0ZXI+XFxuXFxuICAgIDwvZGl2PlxcbiAgICBcIixcbiAgbW91bnRlZDogZnVuY3Rpb24gbW91bnRlZCgpIHtcbiAgICB2YXIgX3RoaXMgPSB0aGlzO1xuXG4gICAgaWYgKHR5cGVvZiBfdGhpcy5maWVsZF92YWx1ZSA9PT0gJ3N0cmluZycgJiYgV3BjZnRvSXNKc29uU3RyaW5nKF90aGlzLmZpZWxkX3ZhbHVlKSkge1xuICAgICAgX3RoaXMuZmllbGRfdmFsdWUgPSBKU09OLnBhcnNlKF90aGlzLmZpZWxkX3ZhbHVlKTtcbiAgICB9XG5cbiAgICBpZiAodHlwZW9mIF90aGlzLmZpZWxkX3ZhbHVlICE9PSAndW5kZWZpbmVkJyAmJiB0eXBlb2YgX3RoaXMuZmllbGRfdmFsdWUgIT09ICdzdHJpbmcnKSB7XG4gICAgICBfdGhpcy4kc2V0KF90aGlzLCAncmVwZWF0ZXJfdmFsdWVzJywgX3RoaXMuZmllbGRfdmFsdWUpO1xuXG4gICAgICBfdGhpcy5yZXBlYXRlcl92YWx1ZXMuZm9yRWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICAgIF90aGlzLnJlcGVhdGVyLnB1c2goe30pO1xuICAgICAgfSk7XG4gICAgfVxuICB9LFxuICBtZXRob2RzOiB7XG4gICAgYWRkQXJlYTogZnVuY3Rpb24gYWRkQXJlYSgpIHtcbiAgICAgIHRoaXMucmVwZWF0ZXIucHVzaCh7XG4gICAgICAgIGNsb3NlZF90YWI6IHRydWVcbiAgICAgIH0pO1xuICAgICAgdmFyIGVsID0gJ3dwY2Z0by1yZXBlYXRlcl8nICsgdGhpcy5maWVsZF9uYW1lICsgJ18nICsgKHRoaXMucmVwZWF0ZXIubGVuZ3RoIC0gMSk7XG4gICAgICBWdWUubmV4dFRpY2soZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAodHlwZW9mIGpRdWVyeSAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICB2YXIgJCA9IGpRdWVyeTtcbiAgICAgICAgICAkKFtkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQsIGRvY3VtZW50LmJvZHldKS5hbmltYXRlKHtcbiAgICAgICAgICAgIHNjcm9sbFRvcDogJChcIi5cIiArIGVsKS5vZmZzZXQoKS50b3AgLSA0MFxuICAgICAgICAgIH0sIDQwMCk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH0sXG4gICAgdG9nZ2xlQXJlYTogZnVuY3Rpb24gdG9nZ2xlQXJlYShhcmVhKSB7XG4gICAgICB2YXIgY3VycmVudFN0YXRlID0gdHlwZW9mIGFyZWFbJ2Nsb3NlZF90YWInXSAhPT0gJ3VuZGVmaW5lZCcgPyBhcmVhWydjbG9zZWRfdGFiJ10gOiBmYWxzZTtcbiAgICAgIHRoaXMuJHNldChhcmVhLCAnY2xvc2VkX3RhYicsICFjdXJyZW50U3RhdGUpO1xuICAgIH0sXG4gICAgcmVtb3ZlQXJlYTogZnVuY3Rpb24gcmVtb3ZlQXJlYShhcmVhSW5kZXgpIHtcbiAgICAgIGlmIChjb25maXJtKCdEbyB5b3VyIHJlYWxseSB3YW50IHRvIGRlbGV0ZSB0aGlzIGZpZWxkPycpKSB7XG4gICAgICAgIHRoaXMucmVwZWF0ZXIuc3BsaWNlKGFyZWFJbmRleCwgMSk7XG4gICAgICB9XG4gICAgfSxcbiAgICBnZXRGaWVsZFZhbHVlOiBmdW5jdGlvbiBnZXRGaWVsZFZhbHVlKGtleSwgZmllbGQsIGZpZWxkX25hbWUpIHtcbiAgICAgIGlmICh0eXBlb2YgdGhpcy5yZXBlYXRlcl92YWx1ZXMgPT09ICd1bmRlZmluZWQnKSByZXR1cm4gZmllbGQudmFsdWU7XG4gICAgICBpZiAodHlwZW9mIHRoaXMucmVwZWF0ZXJfdmFsdWVzW2tleV0gPT09ICd1bmRlZmluZWQnKSByZXR1cm4gZmllbGQudmFsdWU7XG4gICAgICBpZiAodHlwZW9mIHRoaXMucmVwZWF0ZXJfdmFsdWVzW2tleV1bZmllbGRfbmFtZV0gPT09ICd1bmRlZmluZWQnKSByZXR1cm4gZmllbGQudmFsdWU7XG4gICAgICByZXR1cm4gdGhpcy5yZXBlYXRlcl92YWx1ZXNba2V5XVtmaWVsZF9uYW1lXTtcbiAgICB9XG4gIH0sXG4gIHdhdGNoOiB7XG4gICAgcmVwZWF0ZXI6IHtcbiAgICAgIGRlZXA6IHRydWUsXG4gICAgICBoYW5kbGVyOiBmdW5jdGlvbiBoYW5kbGVyKHJlcGVhdGVyKSB7XG4gICAgICAgIHRoaXMuJGVtaXQoJ3dwY2Z0by1nZXQtdmFsdWUnLCByZXBlYXRlcik7XG4gICAgICB9XG4gICAgfVxuICB9XG59KTsiXX0=
|
|
},{}]},{},[1]) |