Remove unused blade settings pages not linked from UI Convert remaining frontend pages to SPA actions Convert settings user_settings and general to SPA actions Convert settings profile pages to SPA actions Convert contacts and projects add/edit pages to SPA actions Convert clients add/edit page to SPA action with loading pattern Refactor component scoped IDs from $id to $sid Fix jqhtml comment syntax and implement universal error component system Update all application code to use new unified error system Remove all backwards compatibility - unified error system complete Phase 5: Remove old response classes Phase 3-4: Ajax response handler sends new format, old helpers deprecated Phase 2: Add client-side unified error foundation Phase 1: Add server-side unified error foundation Add unified Ajax error response system with constants 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
244 lines
29 KiB
JavaScript
Executable File
244 lines
29 KiB
JavaScript
Executable File
"use strict";
|
|
|
|
/**
|
|
* Phone_Text_Input
|
|
*
|
|
* Extends Text_Input to provide automatic phone number formatting.
|
|
*
|
|
* Features:
|
|
* - US Mode (default): Formats as (XXX) XXX-XXXX on every keystroke
|
|
* - International Mode: Triggered by starting with '+', disables formatting
|
|
* - val() getter returns formatted string as displayed
|
|
* - val() setter accepts any format and displays appropriately
|
|
*
|
|
* Usage:
|
|
* <Phone_Text_Input $placeholder="Phone number" />
|
|
*
|
|
* Behavior:
|
|
* - Type "5551234567" -> displays "(555) 123-4567", val() returns "(555) 123-4567"
|
|
* - Type "+44 20 7123 4567" -> displays as typed, val() returns "+44 20 7123 4567"
|
|
* - Leading "1" is stripped: "15551234567" -> "(555) 123-4567"
|
|
*/
|
|
class Phone_Text_Input extends Text_Input {
|
|
on_create() {
|
|
super.on_create();
|
|
this._is_international = false;
|
|
}
|
|
|
|
/**
|
|
* Check if input is in international mode (starts with +)
|
|
* @param {string} value
|
|
* @returns {boolean}
|
|
*/
|
|
_check_international_mode(value) {
|
|
return value && str(value).charAt(0) === '+';
|
|
}
|
|
|
|
/**
|
|
* Format US phone number as (XXX) XXX-XXXX
|
|
* @param {string} digits - Clean numeric string (should be 10 digits or less after processing)
|
|
* @returns {string} Formatted phone number
|
|
*/
|
|
_format_us_phone(digits) {
|
|
// Format based on length (assumes digits are already cleaned and limited to 10)
|
|
if (digits.length >= 6) {
|
|
// (XXX) XXX-XXXX
|
|
return '(' + digits.substr(0, 3) + ') ' + digits.substr(3, 3) + '-' + digits.substr(6);
|
|
} else if (digits.length >= 3) {
|
|
// (XXX) XXX
|
|
return '(' + digits.substr(0, 3) + ') ' + digits.substr(3);
|
|
} else if (digits.length > 0) {
|
|
// (XX
|
|
return '(' + digits;
|
|
}
|
|
return digits;
|
|
}
|
|
|
|
/**
|
|
* val() - Get or set the phone number
|
|
* Getter returns formatted value as displayed (with parens, dashes, etc)
|
|
* Setter accepts anything and formats appropriately
|
|
* @param {string} [value]
|
|
* @returns {string}
|
|
*/
|
|
val(value) {
|
|
if (arguments.length === 0) {
|
|
// Getter - return the formatted value as displayed
|
|
return this.$sid('input').val() || '';
|
|
} else {
|
|
// Setter - format and display
|
|
if (!value) {
|
|
this.data.value = '';
|
|
if (this.$sid('input').exists()) {
|
|
this.$sid('input').val('');
|
|
}
|
|
return;
|
|
}
|
|
const str_value = str(value);
|
|
if (this._check_international_mode(str_value)) {
|
|
// International mode - no formatting
|
|
this.data.value = str_value;
|
|
if (this.$sid('input').exists()) {
|
|
this.$sid('input').val(str_value);
|
|
}
|
|
} else {
|
|
// US mode - clean digits and format
|
|
const digits = str_value.replace(/[^0-9]/g, '');
|
|
|
|
// Determine which digits to format
|
|
let digits_to_format;
|
|
if (digits.length === 11 && digits.charAt(0) === '1' && /[2-9]/.test(digits.charAt(1))) {
|
|
// Strip US country code
|
|
digits_to_format = digits.substr(1);
|
|
} else if (digits.length > 10) {
|
|
// Take first 10
|
|
digits_to_format = digits.substr(0, 10);
|
|
} else {
|
|
// Use as-is
|
|
digits_to_format = digits;
|
|
}
|
|
const formatted = this._format_us_phone(digits_to_format);
|
|
this.data.value = formatted;
|
|
if (this.$sid('input').exists()) {
|
|
this.$sid('input').val(formatted);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
on_ready() {
|
|
super.on_ready();
|
|
const $input = this.$sid('input');
|
|
let _last_cursor_position = null;
|
|
|
|
// Handle keydown to intercept backspace at end of string
|
|
$input.on('keydown', e => {
|
|
const raw = $input.val();
|
|
|
|
// Skip if international mode
|
|
if (this._check_international_mode(raw)) {
|
|
return;
|
|
}
|
|
|
|
// Only handle backspace key
|
|
if (e.key !== 'Backspace') {
|
|
return;
|
|
}
|
|
const input_element = $input[0];
|
|
const cursor_pos = input_element.selectionStart;
|
|
const cursor_end = input_element.selectionEnd;
|
|
const value_length = raw.length;
|
|
|
|
// Only handle if cursor is at the end and no selection
|
|
if (cursor_pos === value_length && cursor_pos === cursor_end) {
|
|
// Check if character before cursor is non-numeric
|
|
if (cursor_pos > 0) {
|
|
const char_before = raw.charAt(cursor_pos - 1);
|
|
if (!/[0-9]/.test(char_before)) {
|
|
// Character before cursor is not a digit
|
|
// Delete the last digit instead
|
|
e.preventDefault();
|
|
const digits = raw.replace(/[^0-9]/g, '');
|
|
if (digits.length > 0) {
|
|
const new_digits = digits.substr(0, digits.length - 1);
|
|
const formatted = this._format_us_phone(new_digits);
|
|
$input.val(formatted);
|
|
|
|
// Place cursor at end
|
|
setTimeout(() => {
|
|
const new_length = $input.val().length;
|
|
input_element.setSelectionRange(new_length, new_length);
|
|
}, 0);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
// Handle input event for live formatting
|
|
$input.on('input', () => {
|
|
const raw = $input.val();
|
|
if (this._check_international_mode(raw)) {
|
|
// International mode - allow anything
|
|
this._is_international = true;
|
|
// No formatting, no restrictions
|
|
return;
|
|
}
|
|
|
|
// US mode
|
|
this._is_international = false;
|
|
const input_element = $input[0];
|
|
const cursor_pos = input_element.selectionStart;
|
|
const value_length = raw.length;
|
|
|
|
// Only apply live formatting if cursor is at the end
|
|
if (cursor_pos === value_length) {
|
|
// Remove any non-digit, non-formatting characters
|
|
const cleaned = raw.replace(/[^0-9\s\-()]/g, '');
|
|
const digits = cleaned.replace(/[^0-9]/g, '');
|
|
|
|
// Determine which digits to format
|
|
let digits_to_format;
|
|
if (digits.length === 11 && digits.charAt(0) === '1' && /[2-9]/.test(digits.charAt(1))) {
|
|
// Exactly 11 digits starting with "1" followed by valid area code digit (2-9)
|
|
// This is a US country code - strip the leading 1
|
|
digits_to_format = digits.substr(1);
|
|
} else if (digits.length > 10) {
|
|
// More than 10 digits - just take the first 10 and ignore the rest
|
|
digits_to_format = digits.substr(0, 10);
|
|
} else {
|
|
// 10 or fewer digits - use as-is
|
|
digits_to_format = digits;
|
|
}
|
|
|
|
// Format the digits
|
|
const formatted = this._format_us_phone(digits_to_format);
|
|
$input.val(formatted);
|
|
} else {
|
|
// Cursor is not at end - user is editing in the middle
|
|
// Don't format, just clean invalid characters
|
|
const cleaned = raw.replace(/[^0-9\s\-()]/g, '');
|
|
if (cleaned !== raw) {
|
|
$input.val(cleaned);
|
|
// Restore cursor position
|
|
input_element.setSelectionRange(cursor_pos, cursor_pos);
|
|
}
|
|
}
|
|
});
|
|
|
|
// Handle blur to reformat when done editing
|
|
$input.on('blur', () => {
|
|
const raw = $input.val();
|
|
|
|
// Skip if international mode or empty
|
|
if (this._check_international_mode(raw) || !raw) {
|
|
return;
|
|
}
|
|
|
|
// Reformat the entire value on blur
|
|
const digits = raw.replace(/[^0-9]/g, '');
|
|
|
|
// Determine which digits to format
|
|
let digits_to_format;
|
|
if (digits.length === 11 && digits.charAt(0) === '1' && /[2-9]/.test(digits.charAt(1))) {
|
|
// Exactly 11 digits starting with "1" followed by valid area code digit (2-9)
|
|
// This is a US country code - strip the leading 1
|
|
digits_to_format = digits.substr(1);
|
|
} else if (digits.length > 10) {
|
|
// More than 10 digits - just take the first 10
|
|
digits_to_format = digits.substr(0, 10);
|
|
} else {
|
|
// 10 or fewer digits - use as-is
|
|
digits_to_format = digits;
|
|
}
|
|
const formatted = this._format_us_phone(digits_to_format);
|
|
$input.val(formatted);
|
|
});
|
|
|
|
// Initialize formatting if there's a value
|
|
const initial_value = $input.val();
|
|
if (initial_value) {
|
|
this.val(initial_value);
|
|
}
|
|
}
|
|
}
|
|
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJQaG9uZV9UZXh0X0lucHV0IiwiVGV4dF9JbnB1dCIsIm9uX2NyZWF0ZSIsIl9pc19pbnRlcm5hdGlvbmFsIiwiX2NoZWNrX2ludGVybmF0aW9uYWxfbW9kZSIsInZhbHVlIiwic3RyIiwiY2hhckF0IiwiX2Zvcm1hdF91c19waG9uZSIsImRpZ2l0cyIsImxlbmd0aCIsInN1YnN0ciIsInZhbCIsImFyZ3VtZW50cyIsIiRpZCIsImRhdGEiLCJleGlzdHMiLCJzdHJfdmFsdWUiLCJyZXBsYWNlIiwiZGlnaXRzX3RvX2Zvcm1hdCIsInRlc3QiLCJmb3JtYXR0ZWQiLCJvbl9yZWFkeSIsIiRpbnB1dCIsIl9sYXN0X2N1cnNvcl9wb3NpdGlvbiIsIm9uIiwiZSIsInJhdyIsImtleSIsImlucHV0X2VsZW1lbnQiLCJjdXJzb3JfcG9zIiwic2VsZWN0aW9uU3RhcnQiLCJjdXJzb3JfZW5kIiwic2VsZWN0aW9uRW5kIiwidmFsdWVfbGVuZ3RoIiwiY2hhcl9iZWZvcmUiLCJwcmV2ZW50RGVmYXVsdCIsIm5ld19kaWdpdHMiLCJzZXRUaW1lb3V0IiwibmV3X2xlbmd0aCIsInNldFNlbGVjdGlvblJhbmdlIiwiY2xlYW5lZCIsImluaXRpYWxfdmFsdWUiXSwic291cmNlcyI6WyJyc3gvdGhlbWUvY29tcG9uZW50cy9pbnB1dHMvcGhvbmVfdGV4dF9pbnB1dC5qcyJdLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIFBob25lX1RleHRfSW5wdXRcbiAqXG4gKiBFeHRlbmRzIFRleHRfSW5wdXQgdG8gcHJvdmlkZSBhdXRvbWF0aWMgcGhvbmUgbnVtYmVyIGZvcm1hdHRpbmcuXG4gKlxuICogRmVhdHVyZXM6XG4gKiAtIFVTIE1vZGUgKGRlZmF1bHQpOiBGb3JtYXRzIGFzIChYWFgpIFhYWC1YWFhYIG9uIGV2ZXJ5IGtleXN0cm9rZVxuICogLSBJbnRlcm5hdGlvbmFsIE1vZGU6IFRyaWdnZXJlZCBieSBzdGFydGluZyB3aXRoICcrJywgZGlzYWJsZXMgZm9ybWF0dGluZ1xuICogLSB2YWwoKSBnZXR0ZXIgcmV0dXJucyBmb3JtYXR0ZWQgc3RyaW5nIGFzIGRpc3BsYXllZFxuICogLSB2YWwoKSBzZXR0ZXIgYWNjZXB0cyBhbnkgZm9ybWF0IGFuZCBkaXNwbGF5cyBhcHByb3ByaWF0ZWx5XG4gKlxuICogVXNhZ2U6XG4gKiAgIDxQaG9uZV9UZXh0X0lucHV0ICRwbGFjZWhvbGRlcj1cIlBob25lIG51bWJlclwiIC8+XG4gKlxuICogQmVoYXZpb3I6XG4gKiAtIFR5cGUgXCI1NTUxMjM0NTY3XCIgLT4gZGlzcGxheXMgXCIoNTU1KSAxMjMtNDU2N1wiLCB2YWwoKSByZXR1cm5zIFwiKDU1NSkgMTIzLTQ1NjdcIlxuICogLSBUeXBlIFwiKzQ0IDIwIDcxMjMgNDU2N1wiIC0+IGRpc3BsYXlzIGFzIHR5cGVkLCB2YWwoKSByZXR1cm5zIFwiKzQ0IDIwIDcxMjMgNDU2N1wiXG4gKiAtIExlYWRpbmcgXCIxXCIgaXMgc3RyaXBwZWQ6IFwiMTU1NTEyMzQ1NjdcIiAtPiBcIig1NTUpIDEyMy00NTY3XCJcbiAqL1xuY2xhc3MgUGhvbmVfVGV4dF9JbnB1dCBleHRlbmRzIFRleHRfSW5wdXQge1xuICAgIG9uX2NyZWF0ZSgpIHtcbiAgICAgICAgc3VwZXIub25fY3JlYXRlKCk7XG4gICAgICAgIHRoaXMuX2lzX2ludGVybmF0aW9uYWwgPSBmYWxzZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDaGVjayBpZiBpbnB1dCBpcyBpbiBpbnRlcm5hdGlvbmFsIG1vZGUgKHN0YXJ0cyB3aXRoICspXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHZhbHVlXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59XG4gICAgICovXG4gICAgX2NoZWNrX2ludGVybmF0aW9uYWxfbW9kZSh2YWx1ZSkge1xuICAgICAgICByZXR1cm4gdmFsdWUgJiYgc3RyKHZhbHVlKS5jaGFyQXQoMCkgPT09ICcrJztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBGb3JtYXQgVVMgcGhvbmUgbnVtYmVyIGFzIChYWFgpIFhYWC1YWFhYXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGRpZ2l0cyAtIENsZWFuIG51bWVyaWMgc3RyaW5nIChzaG91bGQgYmUgMTAgZGlnaXRzIG9yIGxlc3MgYWZ0ZXIgcHJvY2Vzc2luZylcbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfSBGb3JtYXR0ZWQgcGhvbmUgbnVtYmVyXG4gICAgICovXG4gICAgX2Zvcm1hdF91c19waG9uZShkaWdpdHMpIHtcbiAgICAgICAgLy8gRm9ybWF0IGJhc2VkIG9uIGxlbmd0aCAoYXNzdW1lcyBkaWdpdHMgYXJlIGFscmVhZHkgY2xlYW5lZCBhbmQgbGltaXRlZCB0byAxMClcbiAgICAgICAgaWYgKGRpZ2l0cy5sZW5ndGggPj0gNikge1xuICAgICAgICAgICAgLy8gKFhYWCkgWFhYLVhYWFhcbiAgICAgICAgICAgIHJldHVybiAnKCcgKyBkaWdpdHMuc3Vic3RyKDAsIDMpICsgJykgJyArIGRpZ2l0cy5zdWJzdHIoMywgMykgKyAnLScgKyBkaWdpdHMuc3Vic3RyKDYpO1xuICAgICAgICB9IGVsc2UgaWYgKGRpZ2l0cy5sZW5ndGggPj0gMykge1xuICAgICAgICAgICAgLy8gKFhYWCkgWFhYXG4gICAgICAgICAgICByZXR1cm4gJygnICsgZGlnaXRzLnN1YnN0cigwLCAzKSArICcpICcgKyBkaWdpdHMuc3Vic3RyKDMpO1xuICAgICAgICB9IGVsc2UgaWYgKGRpZ2l0cy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAvLyAoWFhcbiAgICAgICAgICAgIHJldHVybiAnKCcgKyBkaWdpdHM7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gZGlnaXRzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIHZhbCgpIC0gR2V0IG9yIHNldCB0aGUgcGhvbmUgbnVtYmVyXG4gICAgICogR2V0dGVyIHJldHVybnMgZm9ybWF0dGVkIHZhbHVlIGFzIGRpc3BsYXllZCAod2l0aCBwYXJlbnMsIGRhc2hlcywgZXRjKVxuICAgICAqIFNldHRlciBhY2NlcHRzIGFueXRoaW5nIGFuZCBmb3JtYXRzIGFwcHJvcHJpYXRlbHlcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gW3ZhbHVlXVxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9XG4gICAgICovXG4gICAgdmFsKHZhbHVlKSB7XG4gICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAvLyBHZXR0ZXIgLSByZXR1cm4gdGhlIGZvcm1hdHRlZCB2YWx1ZSBhcyBkaXNwbGF5ZWRcbiAgICAgICAgICAgIHJldHVybiB0aGlzLiRpZCgnaW5wdXQnKS52YWwoKSB8fCAnJztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIFNldHRlciAtIGZvcm1hdCBhbmQgZGlzcGxheVxuICAgICAgICAgICAgaWYgKCF2YWx1ZSkge1xuICAgICAgICAgICAgICAgIHRoaXMuZGF0YS52YWx1ZSA9ICcnO1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLiRpZCgnaW5wdXQnKS5leGlzdHMoKSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLiRpZCgnaW5wdXQnKS52YWwoJycpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGNvbnN0IHN0cl92YWx1ZSA9IHN0cih2YWx1ZSk7XG5cbiAgICAgICAgICAgIGlmICh0aGlzLl9jaGVja19pbnRlcm5hdGlvbmFsX21vZGUoc3RyX3ZhbHVlKSkge1xuICAgICAgICAgICAgICAgIC8vIEludGVybmF0aW9uYWwgbW9kZSAtIG5vIGZvcm1hdHRpbmdcbiAgICAgICAgICAgICAgICB0aGlzLmRhdGEudmFsdWUgPSBzdHJfdmFsdWU7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuJGlkKCdpbnB1dCcpLmV4aXN0cygpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuJGlkKCdpbnB1dCcpLnZhbChzdHJfdmFsdWUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gVVMgbW9kZSAtIGNsZWFuIGRpZ2l0cyBhbmQgZm9ybWF0XG4gICAgICAgICAgICAgICAgY29uc3QgZGlnaXRzID0gc3RyX3ZhbHVlLnJlcGxhY2UoL1teMC05XS9nLCAnJyk7XG5cbiAgICAgICAgICAgICAgICAvLyBEZXRlcm1pbmUgd2hpY2ggZGlnaXRzIHRvIGZvcm1hdFxuICAgICAgICAgICAgICAgIGxldCBkaWdpdHNfdG9fZm9ybWF0O1xuICAgICAgICAgICAgICAgIGlmIChkaWdpdHMubGVuZ3RoID09PSAxMSAmJiBkaWdpdHMuY2hhckF0KDApID09PSAnMScgJiYgL1syLTldLy50ZXN0KGRpZ2l0cy5jaGFyQXQoMSkpKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFN0cmlwIFVTIGNvdW50cnkgY29kZVxuICAgICAgICAgICAgICAgICAgICBkaWdpdHNfdG9fZm9ybWF0ID0gZGlnaXRzLnN1YnN0cigxKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGRpZ2l0cy5sZW5ndGggPiAxMCkge1xuICAgICAgICAgICAgICAgICAgICAvLyBUYWtlIGZpcnN0IDEwXG4gICAgICAgICAgICAgICAgICAgIGRpZ2l0c190b19mb3JtYXQgPSBkaWdpdHMuc3Vic3RyKDAsIDEwKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAvLyBVc2UgYXMtaXNcbiAgICAgICAgICAgICAgICAgICAgZGlnaXRzX3RvX2Zvcm1hdCA9IGRpZ2l0cztcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBjb25zdCBmb3JtYXR0ZWQgPSB0aGlzLl9mb3JtYXRfdXNfcGhvbmUoZGlnaXRzX3RvX2Zvcm1hdCk7XG4gICAgICAgICAgICAgICAgdGhpcy5kYXRhLnZhbHVlID0gZm9ybWF0dGVkO1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLiRpZCgnaW5wdXQnKS5leGlzdHMoKSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLiRpZCgnaW5wdXQnKS52YWwoZm9ybWF0dGVkKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBvbl9yZWFkeSgpIHtcbiAgICAgICAgc3VwZXIub25fcmVhZHkoKTtcblxuICAgICAgICBjb25zdCAkaW5wdXQgPSB0aGlzLiRpZCgnaW5wdXQnKTtcbiAgICAgICAgbGV0IF9sYXN0X2N1cnNvcl9wb3NpdGlvbiA9IG51bGw7XG5cbiAgICAgICAgLy8gSGFuZGxlIGtleWRvd24gdG8gaW50ZXJjZXB0IGJhY2tzcGFjZSBhdCBlbmQgb2Ygc3RyaW5nXG4gICAgICAgICRpbnB1dC5vbigna2V5ZG93bicsIChlKSA9PiB7XG4gICAgICAgICAgICBjb25zdCByYXcgPSAkaW5wdXQudmFsKCk7XG5cbiAgICAgICAgICAgIC8vIFNraXAgaWYgaW50ZXJuYXRpb25hbCBtb2RlXG4gICAgICAgICAgICBpZiAodGhpcy5fY2hlY2tfaW50ZXJuYXRpb25hbF9tb2RlKHJhdykpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIE9ubHkgaGFuZGxlIGJhY2tzcGFjZSBrZXlcbiAgICAgICAgICAgIGlmIChlLmtleSAhPT0gJ0JhY2tzcGFjZScpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGNvbnN0IGlucHV0X2VsZW1lbnQgPSAkaW5wdXRbMF07XG4gICAgICAgICAgICBjb25zdCBjdXJzb3JfcG9zID0gaW5wdXRfZWxlbWVudC5zZWxlY3Rpb25TdGFydDtcbiAgICAgICAgICAgIGNvbnN0IGN1cnNvcl9lbmQgPSBpbnB1dF9lbGVtZW50LnNlbGVjdGlvbkVuZDtcbiAgICAgICAgICAgIGNvbnN0IHZhbHVlX2xlbmd0aCA9IHJhdy5sZW5ndGg7XG5cbiAgICAgICAgICAgIC8vIE9ubHkgaGFuZGxlIGlmIGN1cnNvciBpcyBhdCB0aGUgZW5kIGFuZCBubyBzZWxlY3Rpb25cbiAgICAgICAgICAgIGlmIChjdXJzb3JfcG9zID09PSB2YWx1ZV9sZW5ndGggJiYgY3Vyc29yX3BvcyA9PT0gY3Vyc29yX2VuZCkge1xuICAgICAgICAgICAgICAgIC8vIENoZWNrIGlmIGNoYXJhY3RlciBiZWZvcmUgY3Vyc29yIGlzIG5vbi1udW1lcmljXG4gICAgICAgICAgICAgICAgaWYgKGN1cnNvcl9wb3MgPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGNoYXJfYmVmb3JlID0gcmF3LmNoYXJBdChjdXJzb3JfcG9zIC0gMSk7XG4gICAgICAgICAgICAgICAgICAgIGlmICghL1swLTldLy50ZXN0KGNoYXJfYmVmb3JlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gQ2hhcmFjdGVyIGJlZm9yZSBjdXJzb3IgaXMgbm90IGEgZGlnaXRcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIERlbGV0ZSB0aGUgbGFzdCBkaWdpdCBpbnN0ZWFkXG4gICAgICAgICAgICAgICAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGRpZ2l0cyA9IHJhdy5yZXBsYWNlKC9bXjAtOV0vZywgJycpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGRpZ2l0cy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgbmV3X2RpZ2l0cyA9IGRpZ2l0cy5zdWJzdHIoMCwgZGlnaXRzLmxlbmd0aCAtIDEpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGZvcm1hdHRlZCA9IHRoaXMuX2Zvcm1hdF91c19waG9uZShuZXdfZGlnaXRzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkaW5wdXQudmFsKGZvcm1hdHRlZCk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBQbGFjZSBjdXJzb3IgYXQgZW5kXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG5ld19sZW5ndGggPSAkaW5wdXQudmFsKCkubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnB1dF9lbGVtZW50LnNldFNlbGVjdGlvblJhbmdlKG5ld19sZW5ndGgsIG5ld19sZW5ndGgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0sIDApO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcblxuICAgICAgICAvLyBIYW5kbGUgaW5wdXQgZXZlbnQgZm9yIGxpdmUgZm9ybWF0dGluZ1xuICAgICAgICAkaW5wdXQub24oJ2lucHV0JywgKCkgPT4ge1xuICAgICAgICAgICAgY29uc3QgcmF3ID0gJGlucHV0LnZhbCgpO1xuXG4gICAgICAgICAgICBpZiAodGhpcy5fY2hlY2tfaW50ZXJuYXRpb25hbF9tb2RlKHJhdykpIHtcbiAgICAgICAgICAgICAgICAvLyBJbnRlcm5hdGlvbmFsIG1vZGUgLSBhbGxvdyBhbnl0aGluZ1xuICAgICAgICAgICAgICAgIHRoaXMuX2lzX2ludGVybmF0aW9uYWwgPSB0cnVlO1xuICAgICAgICAgICAgICAgIC8vIE5vIGZvcm1hdHRpbmcsIG5vIHJlc3RyaWN0aW9uc1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gVVMgbW9kZVxuICAgICAgICAgICAgdGhpcy5faXNfaW50ZXJuYXRpb25hbCA9IGZhbHNlO1xuXG4gICAgICAgICAgICBjb25zdCBpbnB1dF9lbGVtZW50ID0gJGlucHV0WzBdO1xuICAgICAgICAgICAgY29uc3QgY3Vyc29yX3BvcyA9IGlucHV0X2VsZW1lbnQuc2VsZWN0aW9uU3RhcnQ7XG4gICAgICAgICAgICBjb25zdCB2YWx1ZV9sZW5ndGggPSByYXcubGVuZ3RoO1xuXG4gICAgICAgICAgICAvLyBPbmx5IGFwcGx5IGxpdmUgZm9ybWF0dGluZyBpZiBjdXJzb3IgaXMgYXQgdGhlIGVuZFxuICAgICAgICAgICAgaWYgKGN1cnNvcl9wb3MgPT09IHZhbHVlX2xlbmd0aCkge1xuICAgICAgICAgICAgICAgIC8vIFJlbW92ZSBhbnkgbm9uLWRpZ2l0LCBub24tZm9ybWF0dGluZyBjaGFyYWN0ZXJzXG4gICAgICAgICAgICAgICAgY29uc3QgY2xlYW5lZCA9IHJhdy5yZXBsYWNlKC9bXjAtOVxcc1xcLSgpXS9nLCAnJyk7XG4gICAgICAgICAgICAgICAgY29uc3QgZGlnaXRzID0gY2xlYW5lZC5yZXBsYWNlKC9bXjAtOV0vZywgJycpO1xuXG4gICAgICAgICAgICAgICAgLy8gRGV0ZXJtaW5lIHdoaWNoIGRpZ2l0cyB0byBmb3JtYXRcbiAgICAgICAgICAgICAgICBsZXQgZGlnaXRzX3RvX2Zvcm1hdDtcblxuICAgICAgICAgICAgICAgIGlmIChkaWdpdHMubGVuZ3RoID09PSAxMSAmJiBkaWdpdHMuY2hhckF0KDApID09PSAnMScgJiYgL1syLTldLy50ZXN0KGRpZ2l0cy5jaGFyQXQoMSkpKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIEV4YWN0bHkgMTEgZGlnaXRzIHN0YXJ0aW5nIHdpdGggXCIxXCIgZm9sbG93ZWQgYnkgdmFsaWQgYXJlYSBjb2RlIGRpZ2l0ICgyLTkpXG4gICAgICAgICAgICAgICAgICAgIC8vIFRoaXMgaXMgYSBVUyBjb3VudHJ5IGNvZGUgLSBzdHJpcCB0aGUgbGVhZGluZyAxXG4gICAgICAgICAgICAgICAgICAgIGRpZ2l0c190b19mb3JtYXQgPSBkaWdpdHMuc3Vic3RyKDEpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoZGlnaXRzLmxlbmd0aCA+IDEwKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIE1vcmUgdGhhbiAxMCBkaWdpdHMgLSBqdXN0IHRha2UgdGhlIGZpcnN0IDEwIGFuZCBpZ25vcmUgdGhlIHJlc3RcbiAgICAgICAgICAgICAgICAgICAgZGlnaXRzX3RvX2Zvcm1hdCA9IGRpZ2l0cy5zdWJzdHIoMCwgMTApO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIDEwIG9yIGZld2VyIGRpZ2l0cyAtIHVzZSBhcy1pc1xuICAgICAgICAgICAgICAgICAgICBkaWdpdHNfdG9fZm9ybWF0ID0gZGlnaXRzO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIEZvcm1hdCB0aGUgZGlnaXRzXG4gICAgICAgICAgICAgICAgY29uc3QgZm9ybWF0dGVkID0gdGhpcy5fZm9ybWF0X3VzX3Bob25lKGRpZ2l0c190b19mb3JtYXQpO1xuICAgICAgICAgICAgICAgICRpbnB1dC52YWwoZm9ybWF0dGVkKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gQ3Vyc29yIGlzIG5vdCBhdCBlbmQgLSB1c2VyIGlzIGVkaXRpbmcgaW4gdGhlIG1pZGRsZVxuICAgICAgICAgICAgICAgIC8vIERvbid0IGZvcm1hdCwganVzdCBjbGVhbiBpbnZhbGlkIGNoYXJhY3RlcnNcbiAgICAgICAgICAgICAgICBjb25zdCBjbGVhbmVkID0gcmF3LnJlcGxhY2UoL1teMC05XFxzXFwtKCldL2csICcnKTtcbiAgICAgICAgICAgICAgICBpZiAoY2xlYW5lZCAhPT0gcmF3KSB7XG4gICAgICAgICAgICAgICAgICAgICRpbnB1dC52YWwoY2xlYW5lZCk7XG4gICAgICAgICAgICAgICAgICAgIC8vIFJlc3RvcmUgY3Vyc29yIHBvc2l0aW9uXG4gICAgICAgICAgICAgICAgICAgIGlucHV0X2VsZW1lbnQuc2V0U2VsZWN0aW9uUmFuZ2UoY3Vyc29yX3BvcywgY3Vyc29yX3Bvcyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcblxuICAgICAgICAvLyBIYW5kbGUgYmx1ciB0byByZWZvcm1hdCB3aGVuIGRvbmUgZWRpdGluZ1xuICAgICAgICAkaW5wdXQub24oJ2JsdXInLCAoKSA9PiB7XG4gICAgICAgICAgICBjb25zdCByYXcgPSAkaW5wdXQudmFsKCk7XG5cbiAgICAgICAgICAgIC8vIFNraXAgaWYgaW50ZXJuYXRpb25hbCBtb2RlIG9yIGVtcHR5XG4gICAgICAgICAgICBpZiAodGhpcy5fY2hlY2tfaW50ZXJuYXRpb25hbF9tb2RlKHJhdykgfHwgIXJhdykge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gUmVmb3JtYXQgdGhlIGVudGlyZSB2YWx1ZSBvbiBibHVyXG4gICAgICAgICAgICBjb25zdCBkaWdpdHMgPSByYXcucmVwbGFjZSgvW14wLTldL2csICcnKTtcblxuICAgICAgICAgICAgLy8gRGV0ZXJtaW5lIHdoaWNoIGRpZ2l0cyB0byBmb3JtYXRcbiAgICAgICAgICAgIGxldCBkaWdpdHNfdG9fZm9ybWF0O1xuXG4gICAgICAgICAgICBpZiAoZGlnaXRzLmxlbmd0aCA9PT0gMTEgJiYgZGlnaXRzLmNoYXJBdCgwKSA9PT0gJzEnICYmIC9bMi05XS8udGVzdChkaWdpdHMuY2hhckF0KDEpKSkge1xuICAgICAgICAgICAgICAgIC8vIEV4YWN0bHkgMTEgZGlnaXRzIHN0YXJ0aW5nIHdpdGggXCIxXCIgZm9sbG93ZWQgYnkgdmFsaWQgYXJlYSBjb2RlIGRpZ2l0ICgyLTkpXG4gICAgICAgICAgICAgICAgLy8gVGhpcyBpcyBhIFVTIGNvdW50cnkgY29kZSAtIHN0cmlwIHRoZSBsZWFkaW5nIDFcbiAgICAgICAgICAgICAgICBkaWdpdHNfdG9fZm9ybWF0ID0gZGlnaXRzLnN1YnN0cigxKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoZGlnaXRzLmxlbmd0aCA+IDEwKSB7XG4gICAgICAgICAgICAgICAgLy8gTW9yZSB0aGFuIDEwIGRpZ2l0cyAtIGp1c3QgdGFrZSB0aGUgZmlyc3QgMTBcbiAgICAgICAgICAgICAgICBkaWdpdHNfdG9fZm9ybWF0ID0gZGlnaXRzLnN1YnN0cigwLCAxMCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIC8vIDEwIG9yIGZld2VyIGRpZ2l0cyAtIHVzZSBhcy1pc1xuICAgICAgICAgICAgICAgIGRpZ2l0c190b19mb3JtYXQgPSBkaWdpdHM7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGNvbnN0IGZvcm1hdHRlZCA9IHRoaXMuX2Zvcm1hdF91c19waG9uZShkaWdpdHNfdG9fZm9ybWF0KTtcbiAgICAgICAgICAgICRpbnB1dC52YWwoZm9ybWF0dGVkKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgLy8gSW5pdGlhbGl6ZSBmb3JtYXR0aW5nIGlmIHRoZXJlJ3MgYSB2YWx1ZVxuICAgICAgICBjb25zdCBpbml0aWFsX3ZhbHVlID0gJGlucHV0LnZhbCgpO1xuICAgICAgICBpZiAoaW5pdGlhbF92YWx1ZSkge1xuICAgICAgICAgICAgdGhpcy52YWwoaW5pdGlhbF92YWx1ZSk7XG4gICAgICAgIH1cbiAgICB9XG59XG4iXSwibWFwcGluZ3MiOiI7O0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxNQUFNQSxnQkFBZ0IsU0FBU0MsVUFBVSxDQUFDO0VBQ3RDQyxTQUFTQSxDQUFBLEVBQUc7SUFDUixLQUFLLENBQUNBLFNBQVMsQ0FBQyxDQUFDO0lBQ2pCLElBQUksQ0FBQ0MsaUJBQWlCLEdBQUcsS0FBSztFQUNsQzs7RUFFQTtBQUNKO0FBQ0E7QUFDQTtBQUNBO0VBQ0lDLHlCQUF5QkEsQ0FBQ0MsS0FBSyxFQUFFO0lBQzdCLE9BQU9BLEtBQUssSUFBSUMsR0FBRyxDQUFDRCxLQUFLLENBQUMsQ0FBQ0UsTUFBTSxDQUFDLENBQUMsQ0FBQyxLQUFLLEdBQUc7RUFDaEQ7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
|