Standardize settings file naming and relocate documentation files Fix code quality violations from rsx:check Reorganize user_management directory into logical subdirectories Move Quill Bundle to core and align with Tom Select pattern Simplify Site Settings page to focus on core site information Complete Phase 5: Multi-tenant authentication with login flow and site selection Add route query parameter rule and synchronize filename validation logic Fix critical bug in UpdateNpmCommand causing missing JavaScript stubs Implement filename convention rule and resolve VS Code auto-rename conflict Implement js-sanitizer RPC server to eliminate 900+ Node.js process spawns Implement RPC server architecture for JavaScript parsing WIP: Add RPC server infrastructure for JS parsing (partial implementation) Update jqhtml terminology from destroy to stop, fix datagrid DOM preservation Add JQHTML-CLASS-01 rule and fix redundant class names Improve code quality rules and resolve violations Remove legacy fatal error format in favor of unified 'fatal' error type Filter internal keys from window.rsxapp output Update button styling and comprehensive form/modal documentation Add conditional fly-in animation for modals Fix non-deterministic bundle compilation 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
201 lines
24 KiB
JavaScript
Executable File
201 lines
24 KiB
JavaScript
Executable File
"use strict";
|
|
|
|
/**
|
|
* Rsx_Form
|
|
*
|
|
* Form container with validation, submission, and widget value management.
|
|
* See rsx_form.jqhtml for full documentation.
|
|
*
|
|
* JavaScript Responsibilities:
|
|
* - Parses and stores initial form data from $data attribute (JSON or object)
|
|
* - Discovers and manages child Widget components via vals() getter/setter
|
|
* - Handles form submission via Ajax to controller/method endpoints
|
|
* - Applies validation errors to fields using Form_Utils
|
|
* - Integrates with Rsx_Tabs for tab-aware error handling
|
|
* - Provides seed() functionality for debug/testing
|
|
* - Manages form state (values, errors) throughout lifecycle
|
|
*/
|
|
class Rsx_Form extends Jqhtml_Component {
|
|
on_create() {
|
|
this.data.values = {}; // Current form values {name: value}
|
|
this.data.errors = {}; // Validation errors {name: error_message}
|
|
this.tabs = null; // Reference to Rsx_Tabs component if present
|
|
|
|
// Parse initial data from $data attribute (e.g., from $data=$client)
|
|
let data = this.args.data;
|
|
if (typeof data === 'string') {
|
|
try {
|
|
// Decode HTML entities before parsing JSON
|
|
// This handles cases where JSON is passed through Blade {!! !!} syntax
|
|
const decoded = $('<textarea>').html(data).text();
|
|
data = json_decode(decoded);
|
|
} catch (e) {
|
|
console.error('Form: Failed to parse data JSON string', e);
|
|
data = {};
|
|
}
|
|
}
|
|
if (data && typeof data === 'object') {
|
|
this.data.values = data;
|
|
}
|
|
}
|
|
on_ready() {
|
|
const that = this;
|
|
|
|
// Validate that error container exists
|
|
if (!this.$id('error').exists()) {
|
|
console.log(this.$.html());
|
|
throw new Error('Rsx_Form requires an error container with $id="error". ' + 'Add <div $id="error"></div> to your form template for displaying validation and error messages.');
|
|
}
|
|
|
|
// Set up seed button handler if in debug mode
|
|
if (window.rsxapp.debug && this.$id('seed_btn').exists()) {
|
|
that.$id('seed_btn').on('click', function () {
|
|
that.seed();
|
|
});
|
|
}
|
|
|
|
// Find child Rsx_Tabs component if present for error handling integration
|
|
const tabs_el = this.$.find('.Rsx_Tabs').first();
|
|
if (tabs_el.length) {
|
|
that.tabs = tabs_el.component();
|
|
}
|
|
|
|
// Automatically wire all submit buttons to call form submit()
|
|
this.$.find('button[type="submit"]').each(function () {
|
|
$(this).on('click', function (e) {
|
|
e.preventDefault();
|
|
that.submit();
|
|
});
|
|
});
|
|
|
|
// Notify all fields to load their initial values
|
|
// This happens in on_ready to ensure all Form_Field children are initialized
|
|
this.vals(this.data.values);
|
|
|
|
// Hide loading spinner and show form content (without re-rendering)
|
|
this.$id('loader').hide();
|
|
this.$id('form_content').show();
|
|
}
|
|
|
|
// Getter or setter for all form values, similar to jquery val
|
|
vals(values) {
|
|
if (values) {
|
|
// Setter
|
|
|
|
this.$.shallowFind('.Widget').each(function () {
|
|
let $widget = $(this);
|
|
let component = $widget.component();
|
|
if (component && 'val' in component) {
|
|
let widget_name = $widget.data('name');
|
|
if (widget_name in values) {
|
|
component.val(values[widget_name]);
|
|
}
|
|
}
|
|
});
|
|
return null;
|
|
} else {
|
|
// Getter
|
|
let data = {};
|
|
|
|
// Get widget values
|
|
this.$.shallowFind('.Widget').each(function () {
|
|
let $widget = $(this);
|
|
let component = $widget.component();
|
|
if (component && 'val' in component) {
|
|
let widget_name = $widget.data('name');
|
|
data[widget_name] = component.val();
|
|
}
|
|
});
|
|
|
|
// Also get regular hidden inputs (non-widget inputs)
|
|
this.$.find('input[type="hidden"][name]').each(function () {
|
|
let $input = $(this);
|
|
let name = $input.attr('name');
|
|
if (name) {
|
|
data[name] = $input.val();
|
|
}
|
|
});
|
|
return data;
|
|
}
|
|
}
|
|
get_error(name) {
|
|
return this.data.errors[name];
|
|
}
|
|
|
|
/**
|
|
* Render an error in the form's error container
|
|
*
|
|
* Handles both field-specific validation errors and generic errors.
|
|
* Can be called by external handlers (e.g., modal on_submit) or internally
|
|
* by the form's own submit() method.
|
|
*
|
|
* @param {Error|Object} error - Error object from Ajax call
|
|
*/
|
|
async render_error(error) {
|
|
// Handle validation errors - apply to fields
|
|
if (error.type === 'form_error' && error.details) {
|
|
await Form_Utils.apply_form_errors(this.$, error.details);
|
|
|
|
// Notify tabs of validation errors for error badges and auto-switching
|
|
if (this.tabs) {
|
|
this.tabs.handle_validation_errors(error.details);
|
|
}
|
|
|
|
// Form_Utils handles all rendering (inline errors + unmatched errors alert)
|
|
// Don't call Rsx.render_error() to avoid duplicate alerts
|
|
return;
|
|
}
|
|
|
|
// For non-form errors (fatal, auth, network, etc.), render in form's error container
|
|
Rsx.render_error(error, this.$id('error'));
|
|
}
|
|
async submit() {
|
|
// Clear any previous errors
|
|
Form_Utils.reset_form_errors(this.$);
|
|
this.$id('error').empty();
|
|
|
|
// Clear tab error badges if tabs are present
|
|
if (this.tabs) {
|
|
this.tabs.clear_error_badges();
|
|
}
|
|
|
|
// Serialize all field values
|
|
let values = this.vals();
|
|
|
|
// Call submit handler
|
|
if (!this.args.controller || !this.args.method) {
|
|
console.error('Form: No controller/method provided');
|
|
throw new Error('Form configuration error: Missing controller or method');
|
|
}
|
|
try {
|
|
// Build Ajax URL from controller and method
|
|
const ajax_url = `/_ajax/${this.args.controller}/${this.args.method}`;
|
|
|
|
// Call Ajax endpoint - response is directly what PHP returned
|
|
const result = await Ajax.call(ajax_url, values);
|
|
|
|
// Success! Handle result
|
|
if (result && result.redirect) {
|
|
// Redirect to URL
|
|
window.location.href = result.redirect;
|
|
} else {
|
|
// Success without redirect
|
|
console.log('Form submitted successfully', result);
|
|
}
|
|
} catch (error) {
|
|
// Render error (handles both validation and generic errors)
|
|
await this.render_error(error);
|
|
}
|
|
}
|
|
async seed() {
|
|
const promises = [];
|
|
this.$.shallowFind('.Form_Field').each(function () {
|
|
let component = $(this).component();
|
|
if (component && 'seed' in component) {
|
|
promises.push(component.seed());
|
|
}
|
|
});
|
|
await Promise.all(promises);
|
|
}
|
|
}
|
|
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJSc3hfRm9ybSIsIkpxaHRtbF9Db21wb25lbnQiLCJvbl9jcmVhdGUiLCJkYXRhIiwidmFsdWVzIiwiZXJyb3JzIiwidGFicyIsImFyZ3MiLCJkZWNvZGVkIiwiJCIsImh0bWwiLCJ0ZXh0IiwianNvbl9kZWNvZGUiLCJlIiwiY29uc29sZSIsImVycm9yIiwib25fcmVhZHkiLCJ0aGF0IiwiJGlkIiwiZXhpc3RzIiwibG9nIiwiRXJyb3IiLCJ3aW5kb3ciLCJyc3hhcHAiLCJkZWJ1ZyIsIm9uIiwic2VlZCIsInRhYnNfZWwiLCJmaW5kIiwiZmlyc3QiLCJsZW5ndGgiLCJjb21wb25lbnQiLCJlYWNoIiwicHJldmVudERlZmF1bHQiLCJzdWJtaXQiLCJ2YWxzIiwiaGlkZSIsInNob3ciLCJzaGFsbG93RmluZCIsIiR3aWRnZXQiLCJ3aWRnZXRfbmFtZSIsInZhbCIsIiRpbnB1dCIsIm5hbWUiLCJhdHRyIiwiZ2V0X2Vycm9yIiwicmVuZGVyX2Vycm9yIiwidHlwZSIsImRldGFpbHMiLCJGb3JtX1V0aWxzIiwiYXBwbHlfZm9ybV9lcnJvcnMiLCJoYW5kbGVfdmFsaWRhdGlvbl9lcnJvcnMiLCJSc3giLCJyZXNldF9mb3JtX2Vycm9ycyIsImVtcHR5IiwiY2xlYXJfZXJyb3JfYmFkZ2VzIiwiY29udHJvbGxlciIsIm1ldGhvZCIsImFqYXhfdXJsIiwicmVzdWx0IiwiQWpheCIsImNhbGwiLCJyZWRpcmVjdCIsImxvY2F0aW9uIiwiaHJlZiIsInByb21pc2VzIiwicHVzaCIsIlByb21pc2UiLCJhbGwiXSwic291cmNlcyI6WyJyc3gvdGhlbWUvY29tcG9uZW50cy9mb3Jtcy9yc3hfZm9ybS5qcyJdLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIFJzeF9Gb3JtXG4gKlxuICogRm9ybSBjb250YWluZXIgd2l0aCB2YWxpZGF0aW9uLCBzdWJtaXNzaW9uLCBhbmQgd2lkZ2V0IHZhbHVlIG1hbmFnZW1lbnQuXG4gKiBTZWUgcnN4X2Zvcm0uanFodG1sIGZvciBmdWxsIGRvY3VtZW50YXRpb24uXG4gKlxuICogSmF2YVNjcmlwdCBSZXNwb25zaWJpbGl0aWVzOlxuICogLSBQYXJzZXMgYW5kIHN0b3JlcyBpbml0aWFsIGZvcm0gZGF0YSBmcm9tICRkYXRhIGF0dHJpYnV0ZSAoSlNPTiBvciBvYmplY3QpXG4gKiAtIERpc2NvdmVycyBhbmQgbWFuYWdlcyBjaGlsZCBXaWRnZXQgY29tcG9uZW50cyB2aWEgdmFscygpIGdldHRlci9zZXR0ZXJcbiAqIC0gSGFuZGxlcyBmb3JtIHN1Ym1pc3Npb24gdmlhIEFqYXggdG8gY29udHJvbGxlci9tZXRob2QgZW5kcG9pbnRzXG4gKiAtIEFwcGxpZXMgdmFsaWRhdGlvbiBlcnJvcnMgdG8gZmllbGRzIHVzaW5nIEZvcm1fVXRpbHNcbiAqIC0gSW50ZWdyYXRlcyB3aXRoIFJzeF9UYWJzIGZvciB0YWItYXdhcmUgZXJyb3IgaGFuZGxpbmdcbiAqIC0gUHJvdmlkZXMgc2VlZCgpIGZ1bmN0aW9uYWxpdHkgZm9yIGRlYnVnL3Rlc3RpbmdcbiAqIC0gTWFuYWdlcyBmb3JtIHN0YXRlICh2YWx1ZXMsIGVycm9ycykgdGhyb3VnaG91dCBsaWZlY3ljbGVcbiAqL1xuY2xhc3MgUnN4X0Zvcm0gZXh0ZW5kcyBKcWh0bWxfQ29tcG9uZW50IHtcbiAgICBvbl9jcmVhdGUoKSB7XG4gICAgICAgIHRoaXMuZGF0YS52YWx1ZXMgPSB7fTsgLy8gQ3VycmVudCBmb3JtIHZhbHVlcyB7bmFtZTogdmFsdWV9XG4gICAgICAgIHRoaXMuZGF0YS5lcnJvcnMgPSB7fTsgLy8gVmFsaWRhdGlvbiBlcnJvcnMge25hbWU6IGVycm9yX21lc3NhZ2V9XG4gICAgICAgIHRoaXMudGFicyA9IG51bGw7IC8vIFJlZmVyZW5jZSB0byBSc3hfVGFicyBjb21wb25lbnQgaWYgcHJlc2VudFxuXG4gICAgICAgIC8vIFBhcnNlIGluaXRpYWwgZGF0YSBmcm9tICRkYXRhIGF0dHJpYnV0ZSAoZS5nLiwgZnJvbSAkZGF0YT0kY2xpZW50KVxuICAgICAgICBsZXQgZGF0YSA9IHRoaXMuYXJncy5kYXRhO1xuXG4gICAgICAgIGlmICh0eXBlb2YgZGF0YSA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgLy8gRGVjb2RlIEhUTUwgZW50aXRpZXMgYmVmb3JlIHBhcnNpbmcgSlNPTlxuICAgICAgICAgICAgICAgIC8vIFRoaXMgaGFuZGxlcyBjYXNlcyB3aGVyZSBKU09OIGlzIHBhc3NlZCB0aHJvdWdoIEJsYWRlIHshISAhIX0gc3ludGF4XG4gICAgICAgICAgICAgICAgY29uc3QgZGVjb2RlZCA9ICQoJzx0ZXh0YXJlYT4nKS5odG1sKGRhdGEpLnRleHQoKTtcbiAgICAgICAgICAgICAgICBkYXRhID0ganNvbl9kZWNvZGUoZGVjb2RlZCk7XG4gICAgICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcignRm9ybTogRmFpbGVkIHRvIHBhcnNlIGRhdGEgSlNPTiBzdHJpbmcnLCBlKTtcbiAgICAgICAgICAgICAgICBkYXRhID0ge307XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoZGF0YSAmJiB0eXBlb2YgZGF0YSA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgICAgIHRoaXMuZGF0YS52YWx1ZXMgPSBkYXRhO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgb25fcmVhZHkoKSB7XG4gICAgICAgIGNvbnN0IHRoYXQgPSB0aGlzO1xuXG4gICAgICAgIC8vIFZhbGlkYXRlIHRoYXQgZXJyb3IgY29udGFpbmVyIGV4aXN0c1xuICAgICAgICBpZiAoIXRoaXMuJGlkKCdlcnJvcicpLmV4aXN0cygpKSB7XG4gICAgICAgICAgICBjb25zb2xlLmxvZyh0aGlzLiQuaHRtbCgpKTtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICAgICAgICAnUnN4X0Zvcm0gcmVxdWlyZXMgYW4gZXJyb3IgY29udGFpbmVyIHdpdGggJGlkPVwiZXJyb3JcIi4gJyArXG4gICAgICAgICAgICAgICAgICAgICdBZGQgPGRpdiAkaWQ9XCJlcnJvclwiPjwvZGl2PiB0byB5b3VyIGZvcm0gdGVtcGxhdGUgZm9yIGRpc3BsYXlpbmcgdmFsaWRhdGlvbiBhbmQgZXJyb3IgbWVzc2FnZXMuJ1xuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFNldCB1cCBzZWVkIGJ1dHRvbiBoYW5kbGVyIGlmIGluIGRlYnVnIG1vZGVcbiAgICAgICAgaWYgKHdpbmRvdy5yc3hhcHAuZGVidWcgJiYgdGhpcy4kaWQoJ3NlZWRfYnRuJykuZXhpc3RzKCkpIHtcbiAgICAgICAgICAgIHRoYXQuJGlkKCdzZWVkX2J0bicpLm9uKCdjbGljaycsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICB0aGF0LnNlZWQoKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gRmluZCBjaGlsZCBSc3hfVGFicyBjb21wb25lbnQgaWYgcHJlc2VudCBmb3IgZXJyb3IgaGFuZGxpbmcgaW50ZWdyYXRpb25cbiAgICAgICAgY29uc3QgdGFic19lbCA9IHRoaXMuJC5maW5kKCcuUnN4X1RhYnMnKS5maXJzdCgpO1xuICAgICAgICBpZiAodGFic19lbC5sZW5ndGgpIHtcbiAgICAgICAgICAgIHRoYXQudGFicyA9IHRhYnNfZWwuY29tcG9uZW50KCk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBBdXRvbWF0aWNhbGx5IHdpcmUgYWxsIHN1Ym1pdCBidXR0b25zIHRvIGNhbGwgZm9ybSBzdWJtaXQoKVxuICAgICAgICB0aGlzLiQuZmluZCgnYnV0dG9uW3R5cGU9XCJzdWJtaXRcIl0nKS5lYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICQodGhpcykub24oJ2NsaWNrJywgZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgICAgICAgdGhhdC5zdWJtaXQoKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcblxuICAgICAgICAvLyBOb3RpZnkgYWxsIGZpZWxkcyB0byBsb2FkIHRoZWlyIGluaXRpYWwgdmFsdWVzXG4gICAgICAgIC8vIFRoaXMgaGFwcGVucyBpbiBvbl9yZWFkeSB0byBlbnN1cmUgYWxsIEZvcm1fRmllbGQgY2hpbGRyZW4gYXJlIGluaXRpYWxpemVkXG4gICAgICAgIHRoaXMudmFscyh0aGlzLmRhdGEudmFsdWVzKTtcblxuICAgICAgICAvLyBIaWRlIGxvYWRpbmcgc3Bpbm5lciBhbmQgc2hvdyBmb3JtIGNvbnRlbnQgKHdpdGhvdXQgcmUtcmVuZGVyaW5nKVxuICAgICAgICB0aGlzLiRpZCgnbG9hZGVyJykuaGlkZSgpO1xuICAgICAgICB0aGlzLiRpZCgnZm9ybV9jb250ZW50Jykuc2hvdygpO1xuICAgIH1cblxuICAgIC8vIEdldHRlciBvciBzZXR0ZXIgZm9yIGFsbCBmb3JtIHZhbHVlcywgc2ltaWxhciB0byBqcXVlcnkgdmFsXG4gICAgdmFscyh2YWx1ZXMpIHtcbiAgICAgICAgaWYgKHZhbHVlcykge1xuICAgICAgICAgICAgLy8gU2V0dGVyXG5cbiAgICAgICAgICAgIHRoaXMuJC5zaGFsbG93RmluZCgnLldpZGdldCcpLmVhY2goZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIGxldCAkd2lkZ2V0ID0gJCh0aGlzKTtcbiAgICAgICAgICAgICAgICBsZXQgY29tcG9uZW50ID0gJHdpZGdldC5jb21wb25lbnQoKTtcbiAgICAgICAgICAgICAgICBpZiAoY29tcG9uZW50ICYmICd2YWwnIGluIGNvbXBvbmVudCkge1xuICAgICAgICAgICAgICAgICAgICBsZXQgd2lkZ2V0X25hbWUgPSAkd2lkZ2V0LmRhdGEoJ25hbWUnKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHdpZGdldF9uYW1lIGluIHZhbHVlcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29tcG9uZW50LnZhbCh2YWx1ZXNbd2lkZ2V0X25hbWVdKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIEdldHRlclxuICAgICAgICAgICAgbGV0IGRhdGEgPSB7fTtcblxuICAgICAgICAgICAgLy8gR2V0IHdpZGdldCB2YWx1ZXNcbiAgICAgICAgICAgIHRoaXMuJC5zaGFsbG93RmluZCgnLldpZGdldCcpLmVhY2goZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIGxldCAkd2lkZ2V0ID0gJCh0aGlzKTtcbiAgICAgICAgICAgICAgICBsZXQgY29tcG9uZW50ID0gJHdpZGdldC5jb21wb25lbnQoKTtcbiAgICAgICAgICAgICAgICBpZiAoY29tcG9uZW50ICYmICd2YWwnIGluIGNvbXBvbmVudCkge1xuICAgICAgICAgICAgICAgICAgICBsZXQgd2lkZ2V0X25hbWUgPSAkd2lkZ2V0LmRhdGEoJ25hbWUnKTtcbiAgICAgICAgICAgICAgICAgICAgZGF0YVt3aWRnZXRfbmFtZV0gPSBjb21wb25lbnQudmFsKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIC8vIEFsc28gZ2V0IHJlZ3VsYXIgaGlkZGVuIGlucHV0cyAobm9uLXdpZGdldCBpbnB1dHMpXG4gICAgICAgICAgICB0aGlzLiQuZmluZCgnaW5wdXRbdHlwZT1cImhpZGRlblwiXVtuYW1lXScpLmVhY2goZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIGxldCAkaW5wdXQgPSAkKHRoaXMpO1xuICAgICAgICAgICAgICAgIGxldCBuYW1lID0gJGlucHV0LmF0dHIoJ25hbWUnKTtcbiAgICAgICAgICAgICAgICBpZiAobmFtZSkge1xuICAgICAgICAgICAgICAgICAgICBkYXRhW25hbWVdID0gJGlucHV0LnZhbCgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICByZXR1cm4gZGF0YTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGdldF9lcnJvcihuYW1lKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmRhdGEuZXJyb3JzW25hbWVdO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlbmRlciBhbiBlcnJvciBpbiB0aGUgZm9ybSdzIGVycm9yIGNvbnRhaW5lclxuICAgICAqXG4gICAgICogSGFuZGxlcyBib3RoIGZpZWxkLXNwZWNpZmljIHZhbGlkYXRpb24gZXJyb3JzIGFuZCBnZW5lcmljIGVycm9ycy5cbiAgICAgKiBDYW4gYmUgY2FsbGVkIGJ5IGV4dGVybmFsIGhhbmRsZXJzIChlLmcuLCBtb2RhbCBvbl9zdWJtaXQpIG9yIGludGVybmFsbHlcbiAgICAgKiBieSB0aGUgZm9ybSdzIG93biBzdWJtaXQoKSBtZXRob2QuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0Vycm9yfE9iamVjdH0gZXJyb3IgLSBFcnJvciBvYmplY3QgZnJvbSBBamF4IGNhbGxcbiAgICAgKi9cbiAgICBhc3luYyByZW5kZXJfZXJyb3IoZXJyb3IpIHtcbiAgICAgICAgLy8gSGFuZGxlIHZhbGlkYXRpb24gZXJyb3JzIC0gYXBwbHkgdG8gZmllbGRzXG4gICAgICAgIGlmIChlcnJvci50eXBlID09PSAnZm9ybV9lcnJvcicgJiYgZXJyb3IuZGV0YWlscykge1xuICAgICAgICAgICAgYXdhaXQgRm9ybV9VdGlscy5hcHBseV9mb3JtX2Vycm9ycyh0aGlzLiQsIGVycm9yLmRldGFpbHMpO1xuXG4gICAgICAgICAgICAvLyBOb3RpZnkgdGFicyBvZiB2YWxpZGF0aW9uIGVycm9ycyBmb3IgZXJyb3IgYmFkZ2VzIGFuZCBhdXRvLXN3aXRjaGluZ1xuICAgICAgICAgICAgaWYgKHRoaXMudGFicykge1xuICAgICAgICAgICAgICAgIHRoaXMudGFicy5oYW5kbGVfdmFsaWRhdGlvbl9lcnJvcnMoZXJyb3IuZGV0YWlscyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIEZvcm1fVXRpbHMgaGFuZGxlcyBhbGwgcmVuZGVyaW5nIChpbmxpbmUgZXJyb3JzICsgdW5tYXRjaGVkIGVycm9ycyBhbGVydClcbiAgICAgICAgICAgIC8vIERvbid0IGNhbGwgUnN4LnJlbmRlcl9lcnJvcigpIHRvIGF2b2lkIGR1cGxpY2F0ZSBhbGVydHNcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIEZvciBub24tZm9ybSBlcnJvcnMgKGZhdGFsLCBhdXRoLCBuZXR3b3JrLCBldGMuKSwgcmVuZGVyIGluIGZvcm0ncyBlcnJvciBjb250YWluZXJcbiAgICAgICAgUnN4LnJlbmRlcl9lcnJvcihlcnJvciwgdGhpcy4kaWQoJ2Vycm9yJykpO1xuICAgIH1cblxuICAgIGFzeW5jIHN1Ym1pdCgpIHtcbiAgICAgICAgLy8gQ2xlYXIgYW55IHByZXZpb3VzIGVycm9yc1xuICAgICAgICBGb3JtX1V0aWxzLnJlc2V0X2Zvcm1fZXJyb3JzKHRoaXMuJCk7XG4gICAgICAgIHRoaXMuJGlkKCdlcnJvcicpLmVtcHR5KCk7XG5cbiAgICAgICAgLy8gQ2xlYXIgdGFiIGVycm9yIGJhZGdlcyBpZiB0YWJzIGFyZSBwcmVzZW50XG4gICAgICAgIGlmICh0aGlzLnRhYnMpIHtcbiAgICAgICAgICAgIHRoaXMudGFicy5jbGVhcl9lcnJvcl9iYWRnZXMoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFNlcmlhbGl6ZSBhbGwgZmllbGQgdmFsdWVzXG4gICAgICAgIGxldCB2YWx1ZXMgPSB0aGlzLnZhbHMoKTtcblxuICAgICAgICAvLyBDYWxsIHN1Ym1pdCBoYW5kbGVyXG4gICAgICAgIGlmICghdGhpcy5hcmdzLmNvbnRyb2xsZXIgfHwgIXRoaXMuYXJncy5tZXRob2QpIHtcbiAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ0Zvcm06IE5vIGNvbnRyb2xsZXIvbWV0aG9kIHByb3ZpZGVkJyk7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Zvcm0gY29uZmlndXJhdGlvbiBlcnJvcjogTWlzc2luZyBjb250cm9sbGVyIG9yIG1ldGhvZCcpO1xuICAgICAgICB9XG5cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIC8vIEJ1aWxkIEFqYXggVVJMIGZyb20gY29udHJvbGxlciBhbmQgbWV0aG9kXG4gICAgICAgICAgICBjb25zdCBhamF4X3VybCA9IGAvX2FqYXgvJHt0aGlzLmFyZ3MuY29udHJvbGxlcn0vJHt0aGlzLmFyZ3MubWV0aG9kfWA7XG5cbiAgICAgICAgICAgIC8vIENhbGwgQWpheCBlbmRwb2ludCAtIHJlc3BvbnNlIGlzIGRpcmVjdGx5IHdoYXQgUEhQIHJldHVybmVkXG4gICAgICAgICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBBamF4LmNhbGwoYWpheF91cmwsIHZhbHVlcyk7XG5cbiAgICAgICAgICAgIC8vIFN1Y2Nlc3MhIEhhbmRsZSByZXN1bHRcbiAgICAgICAgICAgIGlmIChyZXN1bHQgJiYgcmVzdWx0LnJlZGlyZWN0KSB7XG4gICAgICAgICAgICAgICAgLy8gUmVkaXJlY3QgdG8gVVJMXG4gICAgICAgICAgICAgICAgd2luZG93LmxvY2F0aW9uLmhyZWYgPSByZXN1bHQucmVkaXJlY3Q7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIC8vIFN1Y2Nlc3Mgd2l0aG91dCByZWRpcmVjdFxuICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKCdGb3JtIHN1Ym1pdHRlZCBzdWNjZXNzZnVsbHknLCByZXN1bHQpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAgICAgLy8gUmVuZGVyIGVycm9yIChoYW5kbGVzIGJvdGggdmFsaWRhdGlvbiBhbmQgZ2VuZXJpYyBlcnJvcnMpXG4gICAgICAgICAgICBhd2FpdCB0aGlzLnJlbmRlcl9lcnJvcihlcnJvcik7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBhc3luYyBzZWVkKCkge1xuICAgICAgICBjb25zdCBwcm9taXNlcyA9IFtdO1xuICAgICAgICB0aGlzLiQuc2hhbGxvd0ZpbmQoJy5Gb3JtX0ZpZWxkJykuZWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBsZXQgY29tcG9uZW50ID0gJCh0aGlzKS5jb21wb25lbnQoKTtcbiAgICAgICAgICAgIGlmIChjb21wb25lbnQgJiYgJ3NlZWQnIGluIGNvbXBvbmVudCkge1xuICAgICAgICAgICAgICAgIHByb21pc2VzLnB1c2goY29tcG9uZW50LnNlZWQoKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICBhd2FpdCBQcm9taXNlLmFsbChwcm9taXNlcyk7XG4gICAgfVxufVxuIl0sIm1hcHBpbmdzIjoiOztBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE1BQU1BLFFBQVEsU0FBU0MsZ0JBQWdCLENBQUM7RUFDcENDLFNBQVNBLENBQUEsRUFBRztJQUNSLElBQUksQ0FBQ0MsSUFBSSxDQUFDQyxNQUFNLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUN2QixJQUFJLENBQUNELElBQUksQ0FBQ0UsTUFBTSxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDdkIsSUFBSSxDQUFDQyxJQUFJLEdBQUcsSUFBSSxDQUFDLENBQUM7O0lBRWxCO0lBQ0EsSUFBSUgsSUFBSSxHQUFHLElBQUksQ0FBQ0ksSUFBSSxDQUFDSixJQUFJO0lBRXpCLElBQUksT0FBT0EsSUFBSSxLQUFLLFFBQVEsRUFBRTtNQUMxQixJQUFJO1FBQ0E7UUFDQTtRQUNBLE1BQU1LLE9BQU8sR0FBR0MsQ0FBQyxDQUFDLFlBQVksQ0FBQyxDQUFDQyxJQUFJLENBQUNQLElBQUksQ0FBQyxDQUFDUSxJQUFJLENBQUMsQ0FBQztRQUNqRFIsSUFBSSxHQUFHUyxXQUFXLENBQUNKLE9BQU8sQ0FBQztNQUMvQixDQUFDLENBQUMsT0FBT0ssQ0FBQyxFQUFFO1FBQ1JDLE9BQU8sQ0FBQ0MsS0FBSyxDQUFDLHdDQUF3QyxFQUFFRixDQUFDLENBQUM7UUFDMURWLElBQUksR0FBRyxDQUFDLENBQUM7TUFDYjtJQUNKO0lBRUEsSUFBSUEsSUFBSSxJQUFJLE9BQU9BLElBQUksS0FBSyxRQUFRLEVBQUU7TUFDbEMsSUFBSSxDQUFDQSxJQUFJLENBQUNDLE1BQU0sR0FBR0QsSUFBSTtJQUMzQjtFQUNKO0VBRUFhLFFBQVFBLENBQUEsRUFBRztJQUNQLE1BQU1DLElBQUksR0FBRyxJQUFJOztJQUVqQjtJQUNBLElBQUksQ0FBQyxJQUFJLENBQUNDLEdBQUcsQ0FBQyxPQUFPLENBQUMsQ0FBQ0MsTUFBTSxDQUFDLENBQUMsRUFBRTtNQUM3QkwsT0FBTyxDQUFDTSxHQUFHLENBQUMsSUFBSSxDQUFDWCxDQUFDLENBQUNDLElBQUksQ0FBQyxDQUFDLENBQUM7TUFDMUIsTUFBTSxJQUFJVyxLQUFLLENBQ1gseURBQXlELEdBQ3JELGlHQUNSLENBQUM7SUFDTDs7SUFFQTtJQUNBLElBQUlDLE1BQU0sQ0FBQ0MsTUFBTSxDQUFDQyxLQUFLLElBQUksSUFBSSxDQUFDTixHQUFHLENBQUMsVUFBVSxDQUFDLENBQUNDLE1BQU0sQ0FBQyxDQUFDLEVBQUU7TUFDdERGLElBQUksQ0FBQ0MsR0FBRyxDQUFDLFVBQVUsQ0FBQyxDQUFDTyxFQUFFLENBQUMsT0FBTyxFQUFFLFlBQVk7UUFDekNSLElBQUksQ0FBQ1MsSUFBSSxDQUFDLENBQUM7TUFDZixDQUFDLENBQUM7SUFDTjs7SUFFQTtJQUNBLE1BQU1DLE9BQU8sR0FBRyxJQUFJLENBQUNsQixDQUFDLENBQUNtQixJQUFJLENBQUMsV0FBVyxDQUFDLENBQUNDLEtBQUssQ0FBQyxDQUFDO0lBQ2hELElBQUlGLE9BQU8sQ0FBQ0csTUFBTSxFQUFFO01BQ2hCYixJQUFJLENBQUNYLElBQUksR0FBR3FCLE9BQU8sQ0FBQ0ksU0FBUyxDQUFDLENBQUM7SUFDbkM7O0lBRUE7SUFDQSxJQUFJLENBQUN0QixDQUFDLENBQUNtQixJQUFJLENBQUMsdUJBQXVCLENBQUMsQ0FBQ0ksSUFBSSxDQUFDLFlBQVk7TUFDbER2QixDQUFDLENBQUMsSUFBSSxDQUFDLENBQUNnQixFQUFFLENBQUMsT0FBTyxFQUFFLFVBQVVaLENBQUMsRUFBRTtRQUM3QkEsQ0FBQyxDQUFDb0IsY0FBYyxDQUFDLENBQUM7UUFDbEJoQixJQUFJLENBQUNpQixNQUFNLENBQUMsQ0FBQztNQUNqQixDQUFDLENBQUM7SUFDTixDQUFDLENBQUM7O0lBRUY7SUFDQTtJQUNBLElBQUksQ0FBQ0MsSUFBSSxDQUFDLElBQUksQ0FBQ2hDLElBQUksQ0FBQ0MsTUFBTSxDQUFDOztJQUUzQjtJQUNBLElBQUksQ0FBQ2MsR0FBRyxDQUFDLFFBQVEsQ0FBQyxDQUFDa0IsSUFBSSxDQUFDLENBQUM7SUFDekIsSUFBSSxDQUFDbEIsR0FBRyxDQUFDLGNBQWMsQ0FBQyxDQUFDbUIsSUFBSSxDQUFDLENBQUM7RUFDbkM7O0VBRUE7RUFDQUYsSUFBSUEsQ0FBQy9CLE1BQU0sRUFBRTtJQUNULElBQUlBLE1BQU0sRUFBRTtNQUNSOztNQUVBLElBQUksQ0FBQ0ssQ0FBQyxDQUFDNkIsV0FBVyxDQUFDLFNBQVMsQ0FBQyxDQUFDTixJQUFJLENBQUMsWUFBWTtRQUMzQyxJQUFJTyxPQUFPLEdBQUc5QixDQUFDLENBQUMsSUFBSSxDQUFDO1FBQ3JCLElBQUlzQixTQUFTLEdBQUdRLE9BQU8sQ0FBQ1IsU0FBUyxDQUFDLENBQUM7UUFDbkMsSUFBSUEsU0FBUyxJQUFJLEtBQUssSUFBSUEsU0FBUyxFQUFFO1VBQ2pDLElBQUlTLFdBQVcsR0FBR0QsT0FBTyxDQUFDcEMsSUFBSSxDQUFDLE1BQU0sQ0FBQztVQUN0QyxJQUFJcUMsV0FBVyxJQUFJcEMsTUFBTSxFQUFFO1lBQ3ZCMkIsU0FBUyxDQUFDVSxHQUFHLENBQUNyQyxNQUFNLENBQUNvQyxXQUFXLENBQUMsQ0FBQztVQUN0QztRQUNKO01BQ0osQ0FBQyxDQUFDO01BRUYsT0FBTyxJQUFJO0lBQ2YsQ0FBQyxNQUFNO01BQ0g7TUFDQSxJQUFJckMsSUFBSSxHQUFHLENBQUMsQ0FBQzs7TUFFYjtNQUNBLElBQUksQ0FBQ00sQ0FBQyxDQUFDNkIsV0FBVyxDQUFDLFNBQVMsQ0FBQyxDQUFDTixJQUFJLENBQUMsWUFBWTtRQUMzQyxJQUFJTyxPQUFPLEdBQUc5QixDQUFDLENBQUMsSUFBSSxDQUFDO1FBQ3JCLElBQUlzQixTQUFTLEdBQUdRLE9BQU8sQ0FBQ1IsU0FBUyxDQUFDLENBQUM7UUFDbkMsSUFBSUEsU0FBUyxJQUFJLEtBQUssSUFBSUEsU0FBUyxFQUFFO1VBQ2pDLElBQUlTLFdBQVcsR0FBR0QsT0FBTyxDQUFDcEMsSUFBSSxDQUFDLE1BQU0sQ0FBQztVQUN0Q0EsSUFBSSxDQUFDcUMsV0FBVyxDQUFDLEdBQUdULFNBQVMsQ0FBQ1UsR0FBRyxDQUFDLENBQUM7UUFDdkM7TUFDSixDQUFDLENBQUM7O01BRUY7TUFDQSxJQUFJLENBQUNoQyxDQUFDLENBQUNtQixJQUFJLENBQUMsNEJBQTRCLENBQUMsQ0FBQ0ksSUFBSSxDQUFDLFlBQVk7UUFDdkQsSUFBSVUsTUFBTSxHQUFHakMsQ0FBQyxDQUFDLElBQUksQ0FBQztRQUNwQixJQUFJa0MsSUFBSSxHQUFHRCxNQUFNLENBQUNFLElBQUksQ0FBQyxNQUFNLENBQUM7UUFDOUIsSUFBSUQsSUFBSSxFQUFFO1VBQ054QyxJQUFJLENBQUN3QyxJQUFJLENBQUMsR0FBR0QsTUFBTSxDQUFDRCxHQUFHLENBQUMsQ0FBQztRQUM3QjtNQUNKLENBQUMsQ0FBQztNQUVGLE9BQU90QyxJQUFJO0lBQ2Y7RUFDSjtFQUVBMEMsU0FBU0EsQ0FBQ0YsSUFBSSxFQUFFO0lBQ1osT0FBTyxJQUFJLENBQUN4QyxJQUFJLENBQUNFLE1BQU0sQ0FBQ3NDLElBQUksQ0FBQztFQUNqQzs7RUFFQTtBQUNKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7RUFDSSxNQUFNRyxZQUFZQSxDQUFDL0IsS0FBSyxFQUFFO0lBQ3RCO0lBQ0EsSUFBSUEsS0FBSyxDQUFDZ0MsSUFBSSxLQUFLLFlBQVksSUFBSWhDLEtBQUssQ0FBQ2lDLE9BQU8sRUFBRTtNQUM5QyxNQUFNQyxVQUFVLENBQUNDLGlCQUFpQixDQUFDLElBQUksQ0FBQ3pDLENBQUMsRUFBRU0sS0FBSyxDQUFDaUMsT0FBTyxDQUFDOztNQUV6RDtNQUNBLElBQUksSUFBSSxDQUFDMUMsSUFBSSxFQUFFO1FBQ1gsSUFBSSxDQUFDQSxJQUFJLENBQUM2Qyx3QkFBd0IsQ0FBQ3BDLEtBQUssQ0FBQ2lDLE9BQU8sQ0FBQztNQUNyRDs7TUFFQTtNQUNBO01BQ0E7SUFDSjs7SUFFQTtJQUNBSSxHQUFHLENBQUNOLFlBQVksQ0FBQy9CLEtBQUssRUFBRSxJQUFJLENBQUNHLEdBQUcsQ0FBQyxPQUFPLENBQUMsQ0FBQztFQUM5QztFQUVBLE1BQU1nQixNQUFNQSxDQUFBLEVBQUc7SUFDWDtJQUNBZSxVQUFVLENBQUNJLGlCQUFpQixDQUFDLElBQUksQ0FBQzVDLENBQUMsQ0FBQztJQUNwQyxJQUFJLENBQUNTLEdBQUcsQ0FBQyxPQUFPLENBQUMsQ0FBQ29DLEtBQUssQ0FBQyxDQUFDOztJQUV6QjtJQUNBLElBQUksSUFBSSxDQUFDaEQsSUFBSSxFQUFFO01BQ1gsSUFBSSxDQUFDQSxJQUFJLENBQUNpRCxrQkFBa0IsQ0FBQyxDQUFDO0lBQ2xDOztJQUVBO0lBQ0EsSUFBSW5ELE1BQU0sR0FBRyxJQUFJLENBQUMrQixJQUFJLENBQUMsQ0FBQzs7SUFFeEI7SUFDQSxJQUFJLENBQUMsSUFBSSxDQUFDNUIsSUFBSSxDQUFDaUQsVUFBVSxJQUFJLENBQUMsSUFBSSxDQUFDakQsSUFBSSxDQUFDa0QsTUFBTSxFQUFFO01BQzVDM0MsT0FBTyxDQUFDQyxLQUFLLENBQUMscUNBQXFDLENBQUM7TUFDcEQsTUFBTSxJQUFJTSxLQUFLLENBQUMsd0RBQXdELENBQUM7SUFDN0U7SUFFQSxJQUFJO01BQ0E7TUFDQSxNQUFNcUMsUUFBUSxHQUFHLFVBQVUsSUFBSSxDQUFDbkQsSUFBSSxDQUFDaUQsVUFBVSxJQUFJLElBQUksQ0FBQ2pELElBQUksQ0FBQ2tELE1BQU0sRUFBRTs7TUFFckU7TUFDQSxNQUFNRSxNQUFNLEdBQUcsTUFBTUMsSUFBSSxDQUFDQyxJQUFJLENBQUNILFFBQVEsRUFBRXRELE1BQU0sQ0FBQzs7TUFFaEQ7TUFDQSxJQUFJdUQsTUFBTSxJQUFJQSxNQUFNLENBQUNHLFFBQVEsRUFBRTtRQUMzQjtRQUNBeEMsTUFBTSxDQUFDeUMsUUFBUSxDQUFDQyxJQUFJLEdBQUdMLE1BQU0sQ0FBQ0csUUFBUTtNQUMxQyxDQUFDLE1BQU07UUFDSDtRQUNBaEQsT0FBTyxDQUFDTSxHQUFHLENBQUMsNkJBQTZCLEVBQUV1QyxNQUFNLENBQUM7TUFDdEQ7SUFDSixDQUFDLENBQUMsT0FBTzVDLEtBQUssRUFBRTtNQUNaO01BQ0EsTUFBTSxJQUFJLENBQUMrQixZQUFZLENBQUMvQixLQUFLLENBQUM7SUFDbEM7RUFDSjtFQUVBLE1BQU1XLElBQUlBLENBQUEsRUFBRztJQUNULE1BQU11QyxRQUFRLEdBQUcsRUFBRTtJQUNuQixJQUFJLENBQUN4RCxDQUFDLENBQUM2QixXQUFXLENBQUMsYUFBYSxDQUFDLENBQUNOLElBQUksQ0FBQyxZQUFZO01BQy9DLElBQUlELFNBQVMsR0FBR3RCLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQ3NCLFNBQVMsQ0FBQyxDQUFDO01BQ25DLElBQUlBLFNBQVMsSUFBSSxNQUFNLElBQUlBLFNBQVMsRUFBRTtRQUNsQ2tDLFFBQVEsQ0FBQ0MsSUFBSSxDQUFDbkMsU0FBUyxDQUFDTCxJQUFJLENBQUMsQ0FBQyxDQUFDO01BQ25DO0lBQ0osQ0FBQyxDQUFDO0lBQ0YsTUFBTXlDLE9BQU8sQ0FBQ0MsR0FBRyxDQUFDSCxRQUFRLENBQUM7RUFDL0I7QUFDSiIsImlnbm9yZUxpc3QiOltdfQ==
|