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>
238 lines
31 KiB
JavaScript
Executable File
238 lines
31 KiB
JavaScript
Executable File
"use strict";
|
|
|
|
class Data_Table extends Component {
|
|
on_render() {
|
|
// Hide until data loads to prevent visual glitches
|
|
if (Object.keys(this.data).length === 0) {
|
|
this.$sid('footer').css('opacity', '0');
|
|
}
|
|
}
|
|
async on_load() {
|
|
// If data_source provided, fetch data
|
|
if (this.args.data_source) {
|
|
this.data = await this.fetch_data();
|
|
} else if (this.args.columns && this.args.rows) {
|
|
// Use provided static data
|
|
this.data = {
|
|
columns: this.args.columns,
|
|
rows: this.args.rows,
|
|
total: this.args.rows.length,
|
|
start: 1,
|
|
end: this.args.rows.length,
|
|
current_page: 1,
|
|
total_pages: 1
|
|
};
|
|
}
|
|
}
|
|
on_ready() {
|
|
// Show footer after render
|
|
this.$sid('footer').css('opacity', '1');
|
|
|
|
// Build column headers with sorting
|
|
if (this.data.columns) {
|
|
this.build_headers(this.data.columns);
|
|
}
|
|
|
|
// Setup search if enabled
|
|
if (this.args.searchable) {
|
|
this.setup_search();
|
|
}
|
|
|
|
// Setup column visibility toggle if enabled
|
|
if (this.args.column_toggle) {
|
|
this.setup_column_toggle();
|
|
}
|
|
|
|
// Setup bulk actions
|
|
if (this.args.bulk_actions) {
|
|
this.setup_bulk_actions();
|
|
}
|
|
|
|
// Attach row checkbox listeners
|
|
this.$.find('.row-checkbox').on('change', () => {
|
|
this.update_bulk_selection();
|
|
});
|
|
|
|
// Setup pagination click handlers
|
|
const $pagination = this.$sid('pagination');
|
|
$pagination.$.find('.page-link').on('click', e => {
|
|
e.preventDefault();
|
|
const page_text = $(e.target).text();
|
|
if (page_text === 'Previous') {
|
|
this.load_page(this.data.current_page - 1);
|
|
} else if (page_text === 'Next') {
|
|
this.load_page(this.data.current_page + 1);
|
|
} else {
|
|
const page = int(page_text);
|
|
if (!isNaN(page)) {
|
|
this.load_page(page);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
build_headers(columns) {
|
|
const $header_row = this.$sid('header_row');
|
|
|
|
// Skip first cell if bulk actions (already has Bulk_Selection)
|
|
const offset = this.args.bulk_actions ? 1 : 0;
|
|
columns.forEach((col, index) => {
|
|
const $th = $('<th>');
|
|
if (col.sortable !== false) {
|
|
// Create sortable column header
|
|
const $sortable = $('<div>').addClass('Sortable_Column_Header').attr({
|
|
'data-column': col.field,
|
|
'data-sort': 'none'
|
|
});
|
|
const $text = $('<span>').text(col.label || col.field);
|
|
const $icon = $('<span>').attr('data-id', 'sort_icon').html('<i class="text-muted">⇅</i>');
|
|
$sortable.append($text).append(' ').append($icon);
|
|
$sortable.css('cursor', 'pointer');
|
|
$sortable.on('click', () => {
|
|
this.handle_sort(col.field);
|
|
});
|
|
$th.append($sortable);
|
|
} else {
|
|
$th.text(col.label || col.field);
|
|
}
|
|
if (col.width) {
|
|
$th.css('width', col.width);
|
|
}
|
|
$header_row.append($th);
|
|
});
|
|
|
|
// Add actions column header if row_actions enabled
|
|
if (this.args.row_actions) {
|
|
const $th = $('<th>').text('Actions').css('width', '100px');
|
|
$header_row.append($th);
|
|
}
|
|
}
|
|
setup_search() {
|
|
const $container = this.$sid('search_container');
|
|
const $search = $('<input>').attr({
|
|
type: 'search',
|
|
placeholder: 'Search...',
|
|
class: 'form-control form-control-sm'
|
|
}).css('width', '200px');
|
|
$container.append($search);
|
|
let timeout;
|
|
$search.on('input', e => {
|
|
clearTimeout(timeout);
|
|
timeout = setTimeout(() => {
|
|
this.search_query = e.target.value;
|
|
this.reload_data();
|
|
}, 300);
|
|
});
|
|
}
|
|
setup_column_toggle() {
|
|
const $container = this.$sid('column_toggle_container');
|
|
const $toggle = $('<div>').addClass('Column_Visibility_Toggle');
|
|
$container.append($toggle);
|
|
|
|
// Initialize component manually
|
|
const toggle_component = $toggle.component();
|
|
if (toggle_component) {
|
|
toggle_component.args.columns = this.data.columns;
|
|
toggle_component.args.table = this.$sid('table').$;
|
|
toggle_component.build_menu(this.data.columns);
|
|
}
|
|
}
|
|
setup_bulk_actions() {
|
|
const $bulk_selection = this.$sid('bulk_selection');
|
|
$bulk_selection.$.find('input[type="checkbox"]').on('change', e => {
|
|
const checked = e.target.checked;
|
|
this.$.find('.row-checkbox').prop('checked', checked);
|
|
this.update_bulk_selection();
|
|
});
|
|
}
|
|
update_bulk_selection() {
|
|
const checked = this.$.find('.row-checkbox:checked').length;
|
|
const $bulk_bar = this.$sid('bulk_bar');
|
|
if (checked > 0) {
|
|
$bulk_bar.$.show();
|
|
$bulk_bar.set_count(checked);
|
|
} else {
|
|
$bulk_bar.$.hide();
|
|
}
|
|
}
|
|
async handle_sort(field) {
|
|
// Toggle sort direction
|
|
const current = this.sort_field === field ? this.sort_direction : 'none';
|
|
this.sort_direction = current === 'none' ? 'asc' : current === 'asc' ? 'desc' : 'asc';
|
|
this.sort_field = field;
|
|
|
|
// Update sort icon
|
|
this.$sid('header_row').find('[data-column]').each(function () {
|
|
const $sortable = $(this);
|
|
const col = $sortable.attr('data-column');
|
|
const $icon = $sortable.find('[data-id="sort_icon"]');
|
|
if (col === field) {
|
|
$sortable.attr('data-sort', this.sort_direction);
|
|
if (this.sort_direction === 'asc') {
|
|
$icon.html('<i class="text-primary">↑</i>');
|
|
} else if (this.sort_direction === 'desc') {
|
|
$icon.html('<i class="text-primary">↓</i>');
|
|
} else {
|
|
$icon.html('<i class="text-muted">⇅</i>');
|
|
}
|
|
} else {
|
|
$sortable.attr('data-sort', 'none');
|
|
$icon.html('<i class="text-muted">⇅</i>');
|
|
}
|
|
}.bind(this));
|
|
await this.reload_data();
|
|
}
|
|
async load_page(page) {
|
|
if (page < 1 || page > this.data.total_pages) return;
|
|
this.current_page = page;
|
|
await this.reload_data();
|
|
}
|
|
async fetch_data() {
|
|
const params = {
|
|
page: this.current_page || 1,
|
|
per_page: this.args.per_page || 20,
|
|
sort_field: this.sort_field,
|
|
sort_direction: this.sort_direction,
|
|
search: this.search_query
|
|
};
|
|
|
|
// Call data source (can be URL or function)
|
|
if (typeof this.args.data_source === 'function') {
|
|
return await this.args.data_source(params);
|
|
} else {
|
|
const url = new URL(this.args.data_source, window.location.origin);
|
|
Object.keys(params).forEach(key => {
|
|
if (params[key]) url.searchParams.append(key, params[key]);
|
|
});
|
|
const response = await fetch(url);
|
|
return await response.json();
|
|
}
|
|
}
|
|
get_selected_ids() {
|
|
const ids = [];
|
|
this.$.find('.row-checkbox:checked').each(function () {
|
|
ids.push($(this).val());
|
|
});
|
|
return ids;
|
|
}
|
|
async reload_data() {
|
|
// Show loading state
|
|
const $tbody = this.$sid('tbody');
|
|
$tbody.html(`
|
|
<tr>
|
|
<td colspan="100" class="text-center py-5">
|
|
<div class="spinner-border spinner-border-sm" role="status">
|
|
<span class="visually-hidden">Loading...</span>
|
|
</div>
|
|
<div class="mt-2 text-muted">Loading data...</div>
|
|
</td>
|
|
</tr>
|
|
`);
|
|
|
|
// Fetch new data
|
|
this.data = await this.fetch_data();
|
|
|
|
// Re-render entire component
|
|
this.render();
|
|
}
|
|
}
|
|
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJEYXRhX1RhYmxlIiwiSnFodG1sX0NvbXBvbmVudCIsIm9uX3JlbmRlciIsIk9iamVjdCIsImtleXMiLCJkYXRhIiwibGVuZ3RoIiwiJGlkIiwiY3NzIiwib25fbG9hZCIsImFyZ3MiLCJkYXRhX3NvdXJjZSIsImZldGNoX2RhdGEiLCJjb2x1bW5zIiwicm93cyIsInRvdGFsIiwic3RhcnQiLCJlbmQiLCJjdXJyZW50X3BhZ2UiLCJ0b3RhbF9wYWdlcyIsIm9uX3JlYWR5IiwiYnVpbGRfaGVhZGVycyIsInNlYXJjaGFibGUiLCJzZXR1cF9zZWFyY2giLCJjb2x1bW5fdG9nZ2xlIiwic2V0dXBfY29sdW1uX3RvZ2dsZSIsImJ1bGtfYWN0aW9ucyIsInNldHVwX2J1bGtfYWN0aW9ucyIsIiQiLCJmaW5kIiwib24iLCJ1cGRhdGVfYnVsa19zZWxlY3Rpb24iLCIkcGFnaW5hdGlvbiIsImUiLCJwcmV2ZW50RGVmYXVsdCIsInBhZ2VfdGV4dCIsInRhcmdldCIsInRleHQiLCJsb2FkX3BhZ2UiLCJwYWdlIiwiaW50IiwiaXNOYU4iLCIkaGVhZGVyX3JvdyIsIm9mZnNldCIsImZvckVhY2giLCJjb2wiLCJpbmRleCIsIiR0aCIsInNvcnRhYmxlIiwiJHNvcnRhYmxlIiwiYWRkQ2xhc3MiLCJhdHRyIiwiZmllbGQiLCIkdGV4dCIsImxhYmVsIiwiJGljb24iLCJodG1sIiwiYXBwZW5kIiwiaGFuZGxlX3NvcnQiLCJ3aWR0aCIsInJvd19hY3Rpb25zIiwiJGNvbnRhaW5lciIsIiRzZWFyY2giLCJ0eXBlIiwicGxhY2Vob2xkZXIiLCJjbGFzcyIsInRpbWVvdXQiLCJjbGVhclRpbWVvdXQiLCJzZXRUaW1lb3V0Iiwic2VhcmNoX3F1ZXJ5IiwidmFsdWUiLCJyZWxvYWRfZGF0YSIsIiR0b2dnbGUiLCJ0b2dnbGVfY29tcG9uZW50IiwiY29tcG9uZW50IiwidGFibGUiLCJidWlsZF9tZW51IiwiJGJ1bGtfc2VsZWN0aW9uIiwiY2hlY2tlZCIsInByb3AiLCIkYnVsa19iYXIiLCJzaG93Iiwic2V0X2NvdW50IiwiaGlkZSIsImN1cnJlbnQiLCJzb3J0X2ZpZWxkIiwic29ydF9kaXJlY3Rpb24iLCJlYWNoIiwiYmluZCIsInBhcmFtcyIsInBlcl9wYWdlIiwic2VhcmNoIiwidXJsIiwiVVJMIiwid2luZG93IiwibG9jYXRpb24iLCJvcmlnaW4iLCJrZXkiLCJzZWFyY2hQYXJhbXMiLCJyZXNwb25zZSIsImZldGNoIiwianNvbiIsImdldF9zZWxlY3RlZF9pZHMiLCJpZHMiLCJwdXNoIiwidmFsIiwiJHRib2R5IiwicmVuZGVyIl0sInNvdXJjZXMiOlsicnN4L2FwcC9mcm9udGVuZC9jb250YWN0cy9fZGF0YV90YWJsZV9xcS9EYXRhX1RhYmxlLmpzIl0sInNvdXJjZXNDb250ZW50IjpbImNsYXNzIERhdGFfVGFibGUgZXh0ZW5kcyBKcWh0bWxfQ29tcG9uZW50IHtcbiAgICBvbl9yZW5kZXIoKSB7XG4gICAgICAgIC8vIEhpZGUgdW50aWwgZGF0YSBsb2FkcyB0byBwcmV2ZW50IHZpc3VhbCBnbGl0Y2hlc1xuICAgICAgICBpZiAoT2JqZWN0LmtleXModGhpcy5kYXRhKS5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgIHRoaXMuJGlkKCdmb290ZXInKS5jc3MoJ29wYWNpdHknLCAnMCcpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgYXN5bmMgb25fbG9hZCgpIHtcbiAgICAgICAgLy8gSWYgZGF0YV9zb3VyY2UgcHJvdmlkZWQsIGZldGNoIGRhdGFcbiAgICAgICAgaWYgKHRoaXMuYXJncy5kYXRhX3NvdXJjZSkge1xuICAgICAgICAgICAgdGhpcy5kYXRhID0gYXdhaXQgdGhpcy5mZXRjaF9kYXRhKCk7XG4gICAgICAgIH0gZWxzZSBpZiAodGhpcy5hcmdzLmNvbHVtbnMgJiYgdGhpcy5hcmdzLnJvd3MpIHtcbiAgICAgICAgICAgIC8vIFVzZSBwcm92aWRlZCBzdGF0aWMgZGF0YVxuICAgICAgICAgICAgdGhpcy5kYXRhID0ge1xuICAgICAgICAgICAgICAgIGNvbHVtbnM6IHRoaXMuYXJncy5jb2x1bW5zLFxuICAgICAgICAgICAgICAgIHJvd3M6IHRoaXMuYXJncy5yb3dzLFxuICAgICAgICAgICAgICAgIHRvdGFsOiB0aGlzLmFyZ3Mucm93cy5sZW5ndGgsXG4gICAgICAgICAgICAgICAgc3RhcnQ6IDEsXG4gICAgICAgICAgICAgICAgZW5kOiB0aGlzLmFyZ3Mucm93cy5sZW5ndGgsXG4gICAgICAgICAgICAgICAgY3VycmVudF9wYWdlOiAxLFxuICAgICAgICAgICAgICAgIHRvdGFsX3BhZ2VzOiAxLFxuICAgICAgICAgICAgfTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIG9uX3JlYWR5KCkge1xuICAgICAgICAvLyBTaG93IGZvb3RlciBhZnRlciByZW5kZXJcbiAgICAgICAgdGhpcy4kaWQoJ2Zvb3RlcicpLmNzcygnb3BhY2l0eScsICcxJyk7XG5cbiAgICAgICAgLy8gQnVpbGQgY29sdW1uIGhlYWRlcnMgd2l0aCBzb3J0aW5nXG4gICAgICAgIGlmICh0aGlzLmRhdGEuY29sdW1ucykge1xuICAgICAgICAgICAgdGhpcy5idWlsZF9oZWFkZXJzKHRoaXMuZGF0YS5jb2x1bW5zKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFNldHVwIHNlYXJjaCBpZiBlbmFibGVkXG4gICAgICAgIGlmICh0aGlzLmFyZ3Muc2VhcmNoYWJsZSkge1xuICAgICAgICAgICAgdGhpcy5zZXR1cF9zZWFyY2goKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFNldHVwIGNvbHVtbiB2aXNpYmlsaXR5IHRvZ2dsZSBpZiBlbmFibGVkXG4gICAgICAgIGlmICh0aGlzLmFyZ3MuY29sdW1uX3RvZ2dsZSkge1xuICAgICAgICAgICAgdGhpcy5zZXR1cF9jb2x1bW5fdG9nZ2xlKCk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBTZXR1cCBidWxrIGFjdGlvbnNcbiAgICAgICAgaWYgKHRoaXMuYXJncy5idWxrX2FjdGlvbnMpIHtcbiAgICAgICAgICAgIHRoaXMuc2V0dXBfYnVsa19hY3Rpb25zKCk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBBdHRhY2ggcm93IGNoZWNrYm94IGxpc3RlbmVyc1xuICAgICAgICB0aGlzLiQuZmluZCgnLnJvdy1jaGVja2JveCcpLm9uKCdjaGFuZ2UnLCAoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLnVwZGF0ZV9idWxrX3NlbGVjdGlvbigpO1xuICAgICAgICB9KTtcblxuICAgICAgICAvLyBTZXR1cCBwYWdpbmF0aW9uIGNsaWNrIGhhbmRsZXJzXG4gICAgICAgIGNvbnN0ICRwYWdpbmF0aW9uID0gdGhpcy4kaWQoJ3BhZ2luYXRpb24nKTtcbiAgICAgICAgJHBhZ2luYXRpb24uJC5maW5kKCcucGFnZS1saW5rJykub24oJ2NsaWNrJywgKGUpID0+IHtcbiAgICAgICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgIGNvbnN0IHBhZ2VfdGV4dCA9ICQoZS50YXJnZXQpLnRleHQoKTtcbiAgICAgICAgICAgIGlmIChwYWdlX3RleHQgPT09ICdQcmV2aW91cycpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmxvYWRfcGFnZSh0aGlzLmRhdGEuY3VycmVudF9wYWdlIC0gMSk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHBhZ2VfdGV4dCA9PT0gJ05leHQnKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5sb2FkX3BhZ2UodGhpcy5kYXRhLmN1cnJlbnRfcGFnZSArIDEpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBjb25zdCBwYWdlID0gaW50KHBhZ2VfdGV4dCk7XG4gICAgICAgICAgICAgICAgaWYgKCFpc05hTihwYWdlKSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmxvYWRfcGFnZShwYWdlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIGJ1aWxkX2hlYWRlcnMoY29sdW1ucykge1xuICAgICAgICBjb25zdCAkaGVhZGVyX3JvdyA9IHRoaXMuJGlkKCdoZWFkZXJfcm93Jyk7XG5cbiAgICAgICAgLy8gU2tpcCBmaXJzdCBjZWxsIGlmIGJ1bGsgYWN0aW9ucyAoYWxyZWFkeSBoYXMgQnVsa19TZWxlY3Rpb24pXG4gICAgICAgIGNvbnN0IG9mZnNldCA9IHRoaXMuYXJncy5idWxrX2FjdGlvbnMgPyAxIDogMDtcblxuICAgICAgICBjb2x1bW5zLmZvckVhY2goKGNvbCwgaW5kZXgpID0+IHtcbiAgICAgICAgICAgIGNvbnN0ICR0aCA9ICQoJzx0aD4nKTtcblxuICAgICAgICAgICAgaWYgKGNvbC5zb3J0YWJsZSAhPT0gZmFsc2UpIHtcbiAgICAgICAgICAgICAgICAvLyBDcmVhdGUgc29ydGFibGUgY29sdW1uIGhlYWRlclxuICAgICAgICAgICAgICAgIGNvbnN0ICRzb3J0YWJsZSA9ICQoJzxkaXY+JykuYWRkQ2xhc3MoJ1NvcnRhYmxlX0NvbHVtbl9IZWFkZXInKS5hdHRyKHtcbiAgICAgICAgICAgICAgICAgICAgJ2RhdGEtY29sdW1uJzogY29sLmZpZWxkLFxuICAgICAgICAgICAgICAgICAgICAnZGF0YS1zb3J0JzogJ25vbmUnLFxuICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgY29uc3QgJHRleHQgPSAkKCc8c3Bhbj4nKS50ZXh0KGNvbC5sYWJlbCB8fCBjb2wuZmllbGQpO1xuICAgICAgICAgICAgICAgIGNvbnN0ICRpY29uID0gJCgnPHNwYW4+JykuYXR0cignZGF0YS1pZCcsICdzb3J0X2ljb24nKS5odG1sKCc8aSBjbGFzcz1cInRleHQtbXV0ZWRcIj7ih4U8L2k+Jyk7XG5cbiAgICAgICAgICAgICAgICAkc29ydGFibGUuYXBwZW5kKCR0ZXh0KS5hcHBlbmQoJyAnKS5hcHBlbmQoJGljb24pO1xuICAgICAgICAgICAgICAgICRzb3J0YWJsZS5jc3MoJ2N1cnNvcicsICdwb2ludGVyJyk7XG5cbiAgICAgICAgICAgICAgICAkc29ydGFibGUub24oJ2NsaWNrJywgKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmhhbmRsZV9zb3J0KGNvbC5maWVsZCk7XG4gICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICAkdGguYXBwZW5kKCRzb3J0YWJsZSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICR0aC50ZXh0KGNvbC5sYWJlbCB8fCBjb2wuZmllbGQpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoY29sLndpZHRoKSB7XG4gICAgICAgICAgICAgICAgJHRoLmNzcygnd2lkdGgnLCBjb2wud2lkdGgpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAkaGVhZGVyX3Jvdy5hcHBlbmQoJHRoKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgLy8gQWRkIGFjdGlvbnMgY29sdW1uIGhlYWRlciBpZiByb3dfYWN0aW9ucyBlbmFibGVkXG4gICAgICAgIGlmICh0aGlzLmFyZ3Mucm93X2FjdGlvbnMpIHtcbiAgICAgICAgICAgIGNvbnN0ICR0aCA9ICQoJzx0aD4nKS50ZXh0KCdBY3Rpb25zJykuY3NzKCd3aWR0aCcsICcxMDBweCcpO1xuICAgICAgICAgICAgJGhlYWRlcl9yb3cuYXBwZW5kKCR0aCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBzZXR1cF9zZWFyY2goKSB7XG4gICAgICAgIGNvbnN0ICRjb250YWluZXIgPSB0aGlzLiRpZCgnc2VhcmNoX2NvbnRhaW5lcicpO1xuICAgICAgICBjb25zdCAkc2VhcmNoID0gJCgnPGlucHV0PicpXG4gICAgICAgICAgICAuYXR0cih7XG4gICAgICAgICAgICAgICAgdHlwZTogJ3NlYXJjaCcsXG4gICAgICAgICAgICAgICAgcGxhY2Vob2xkZXI6ICdTZWFyY2guLi4nLFxuICAgICAgICAgICAgICAgIGNsYXNzOiAnZm9ybS1jb250cm9sIGZvcm0tY29udHJvbC1zbScsXG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLmNzcygnd2lkdGgnLCAnMjAwcHgnKTtcblxuICAgICAgICAkY29udGFpbmVyLmFwcGVuZCgkc2VhcmNoKTtcblxuICAgICAgICBsZXQgdGltZW91dDtcbiAgICAgICAgJHNlYXJjaC5vbignaW5wdXQnLCAoZSkgPT4ge1xuICAgICAgICAgICAgY2xlYXJUaW1lb3V0KHRpbWVvdXQpO1xuICAgICAgICAgICAgdGltZW91dCA9IHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuc2VhcmNoX3F1ZXJ5ID0gZS50YXJnZXQudmFsdWU7XG4gICAgICAgICAgICAgICAgdGhpcy5yZWxvYWRfZGF0YSgpO1xuICAgICAgICAgICAgfSwgMzAwKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgc2V0dXBfY29sdW1uX3RvZ2dsZSgpIHtcbiAgICAgICAgY29uc3QgJGNvbnRhaW5lciA9IHRoaXMuJGlkKCdjb2x1bW5fdG9nZ2xlX2NvbnRhaW5lcicpO1xuICAgICAgICBjb25zdCAkdG9nZ2xlID0gJCgnPGRpdj4nKS5hZGRDbGFzcygnQ29sdW1uX1Zpc2liaWxpdHlfVG9nZ2xlJyk7XG4gICAgICAgICRjb250YWluZXIuYXBwZW5kKCR0b2dnbGUpO1xuXG4gICAgICAgIC8vIEluaXRpYWxpemUgY29tcG9uZW50IG1hbnVhbGx5XG4gICAgICAgIGNvbnN0IHRvZ2dsZV9jb21wb25lbnQgPSAkdG9nZ2xlLmNvbXBvbmVudCgpO1xuICAgICAgICBpZiAodG9nZ2xlX2NvbXBvbmVudCkge1xuICAgICAgICAgICAgdG9nZ2xlX2NvbXBvbmVudC5hcmdzLmNvbHVtbnMgPSB0aGlzLmRhdGEuY29sdW1ucztcbiAgICAgICAgICAgIHRvZ2dsZV9jb21wb25lbnQuYXJncy50YWJsZSA9IHRoaXMuJGlkKCd0YWJsZScpLiQ7XG4gICAgICAgICAgICB0b2dnbGVfY29tcG9uZW50LmJ1aWxkX21lbnUodGhpcy5kYXRhLmNvbHVtbnMpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgc2V0dXBfYnVsa19hY3Rpb25zKCkge1xuICAgICAgICBjb25zdCAkYnVsa19zZWxlY3Rpb24gPSB0aGlzLiRpZCgnYnVsa19zZWxlY3Rpb24nKTtcbiAgICAgICAgJGJ1bGtfc2VsZWN0aW9uLiQuZmluZCgnaW5wdXRbdHlwZT1cImNoZWNrYm94XCJdJykub24oJ2NoYW5nZScsIChlKSA9PiB7XG4gICAgICAgICAgICBjb25zdCBjaGVja2VkID0gZS50YXJnZXQuY2hlY2tlZDtcbiAgICAgICAgICAgIHRoaXMuJC5maW5kKCcucm93LWNoZWNrYm94JykucHJvcCgnY2hlY2tlZCcsIGNoZWNrZWQpO1xuICAgICAgICAgICAgdGhpcy51cGRhdGVfYnVsa19zZWxlY3Rpb24oKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgdXBkYXRlX2J1bGtfc2VsZWN0aW9uKCkge1xuICAgICAgICBjb25zdCBjaGVja2VkID0gdGhpcy4kLmZpbmQoJy5yb3ctY2hlY2tib3g6Y2hlY2tlZCcpLmxlbmd0aDtcbiAgICAgICAgY29uc3QgJGJ1bGtfYmFyID0gdGhpcy4kaWQoJ2J1bGtfYmFyJyk7XG5cbiAgICAgICAgaWYgKGNoZWNrZWQgPiAwKSB7XG4gICAgICAgICAgICAkYnVsa19iYXIuJC5zaG93KCk7XG4gICAgICAgICAgICAkYnVsa19iYXIuc2V0X2NvdW50KGNoZWNrZWQpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgJGJ1bGtfYmFyLiQuaGlkZSgpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgYXN5bmMgaGFuZGxlX3NvcnQoZmllbGQpIHtcbiAgICAgICAgLy8gVG9nZ2xlIHNvcnQgZGlyZWN0aW9uXG4gICAgICAgIGNvbnN0IGN1cnJlbnQgPSB0aGlzLnNvcnRfZmllbGQgPT09IGZpZWxkID8gdGhpcy5zb3J0X2RpcmVjdGlvbiA6ICdub25lJztcbiAgICAgICAgdGhpcy5zb3J0X2RpcmVjdGlvbiA9IGN1cnJlbnQgPT09ICdub25lJyA/ICdhc2MnIDogY3VycmVudCA9PT0gJ2FzYycgPyAnZGVzYycgOiAnYXNjJztcbiAgICAgICAgdGhpcy5zb3J0X2ZpZWxkID0gZmllbGQ7XG5cbiAgICAgICAgLy8gVXBkYXRlIHNvcnQgaWNvblxuICAgICAgICB0aGlzLiRpZCgnaGVhZGVyX3JvdycpXG4gICAgICAgICAgICAuZmluZCgnW2RhdGEtY29sdW1uXScpXG4gICAgICAgICAgICAuZWFjaChcbiAgICAgICAgICAgICAgICBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0ICRzb3J0YWJsZSA9ICQodGhpcyk7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGNvbCA9ICRzb3J0YWJsZS5hdHRyKCdkYXRhLWNvbHVtbicpO1xuICAgICAgICAgICAgICAgICAgICBjb25zdCAkaWNvbiA9ICRzb3J0YWJsZS5maW5kKCdbZGF0YS1pZD1cInNvcnRfaWNvblwiXScpO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChjb2wgPT09IGZpZWxkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAkc29ydGFibGUuYXR0cignZGF0YS1zb3J0JywgdGhpcy5zb3J0X2RpcmVjdGlvbik7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5zb3J0X2RpcmVjdGlvbiA9PT0gJ2FzYycpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkaWNvbi5odG1sKCc8aSBjbGFzcz1cInRleHQtcHJpbWFyeVwiPuKGkTwvaT4nKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodGhpcy5zb3J0X2RpcmVjdGlvbiA9PT0gJ2Rlc2MnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJGljb24uaHRtbCgnPGkgY2xhc3M9XCJ0ZXh0LXByaW1hcnlcIj7ihpM8L2k+Jyk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICRpY29uLmh0bWwoJzxpIGNsYXNzPVwidGV4dC1tdXRlZFwiPuKHhTwvaT4nKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICRzb3J0YWJsZS5hdHRyKCdkYXRhLXNvcnQnLCAnbm9uZScpO1xuICAgICAgICAgICAgICAgICAgICAgICAgJGljb24uaHRtbCgnPGkgY2xhc3M9XCJ0ZXh0LW11dGVkXCI+4oeFPC9pPicpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfS5iaW5kKHRoaXMpXG4gICAgICAgICAgICApO1xuXG4gICAgICAgIGF3YWl0IHRoaXMucmVsb2FkX2RhdGEoKTtcbiAgICB9XG5cbiAgICBhc3luYyBsb2FkX3BhZ2UocGFnZSkge1xuICAgICAgICBpZiAocGFnZSA8IDEgfHwgcGFnZSA+IHRoaXMuZGF0YS50b3RhbF9wYWdlcykgcmV0dXJuO1xuICAgICAgICB0aGlzLmN1cnJlbnRfcGFnZSA9IHBhZ2U7XG4gICAgICAgIGF3YWl0IHRoaXMucmVsb2FkX2RhdGEoKTtcbiAgICB9XG5cbiAgICBhc3luYyBmZXRjaF9kYXRhKCkge1xuICAgICAgICBjb25zdCBwYXJhbXMgPSB7XG4gICAgICAgICAgICBwYWdlOiB0aGlzLmN1cnJlbnRfcGFnZSB8fCAxLFxuICAgICAgICAgICAgcGVyX3BhZ2U6IHRoaXMuYXJncy5wZXJfcGFnZSB8fCAyMCxcbiAgICAgICAgICAgIHNvcnRfZmllbGQ6IHRoaXMuc29ydF9maWVsZCxcbiAgICAgICAgICAgIHNvcnRfZGlyZWN0aW9uOiB0aGlzLnNvcnRfZGlyZWN0aW9uLFxuICAgICAgICAgICAgc2VhcmNoOiB0aGlzLnNlYXJjaF9xdWVyeSxcbiAgICAgICAgfTtcblxuICAgICAgICAvLyBDYWxsIGRhdGEgc291cmNlIChjYW4gYmUgVVJMIG9yIGZ1bmN0aW9uKVxuICAgICAgICBpZiAodHlwZW9mIHRoaXMuYXJncy5kYXRhX3NvdXJjZSA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgcmV0dXJuIGF3YWl0IHRoaXMuYXJncy5kYXRhX3NvdXJjZShwYXJhbXMpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY29uc3QgdXJsID0gbmV3IFVSTCh0aGlzLmFyZ3MuZGF0YV9zb3VyY2UsIHdpbmRvdy5sb2NhdGlvbi5vcmlnaW4pO1xuICAgICAgICAgICAgT2JqZWN0LmtleXMocGFyYW1zKS5mb3JFYWNoKChrZXkpID0+IHtcbiAgICAgICAgICAgICAgICBpZiAocGFyYW1zW2tleV0pIHVybC5zZWFyY2hQYXJhbXMuYXBwZW5kKGtleSwgcGFyYW1zW2tleV0pO1xuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgZmV0Y2godXJsKTtcbiAgICAgICAgICAgIHJldHVybiBhd2FpdCByZXNwb25zZS5qc29uKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBnZXRfc2VsZWN0ZWRfaWRzKCkge1xuICAgICAgICBjb25zdCBpZHMgPSBbXTtcbiAgICAgICAgdGhpcy4kLmZpbmQoJy5yb3ctY2hlY2tib3g6Y2hlY2tlZCcpLmVhY2goZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgaWRzLnB1c2goJCh0aGlzKS52YWwoKSk7XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gaWRzO1xuICAgIH1cblxuICAgIGFzeW5jIHJlbG9hZF9kYXRhKCkge1xuICAgICAgICAvLyBTaG93IGxvYWRpbmcgc3RhdGVcbiAgICAgICAgY29uc3QgJHRib2R5ID0gdGhpcy4kaWQoJ3Rib2R5Jyk7XG4gICAgICAgICR0Ym9keS5odG1sKGBcbiAgICAgICAgICAgIDx0cj5cbiAgICAgICAgICAgICAgICA8dGQgY29sc3Bhbj1cIjEwMFwiIGNsYXNzPVwidGV4dC1jZW50ZXIgcHktNVwiPlxuICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwic3Bpbm5lci1ib3JkZXIgc3Bpbm5lci1ib3JkZXItc21cIiByb2xlPVwic3RhdHVzXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICA8c3BhbiBjbGFzcz1cInZpc3VhbGx5LWhpZGRlblwiPkxvYWRpbmcuLi48L3NwYW4+XG4gICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwibXQtMiB0ZXh0LW11dGVkXCI+TG9hZGluZyBkYXRhLi4uPC9kaXY+XG4gICAgICAgICAgICAgICAgPC90ZD5cbiAgICAgICAgICAgIDwvdHI+XG4gICAgICAgIGApO1xuXG4gICAgICAgIC8vIEZldGNoIG5ldyBkYXRhXG4gICAgICAgIHRoaXMuZGF0YSA9IGF3YWl0IHRoaXMuZmV0Y2hfZGF0YSgpO1xuXG4gICAgICAgIC8vIFJlLXJlbmRlciBlbnRpcmUgY29tcG9uZW50XG4gICAgICAgIHRoaXMucmVuZGVyKCk7XG4gICAgfVxufVxuIl0sIm1hcHBpbmdzIjoiOztBQUFBLE1BQU1BLFVBQVUsU0FBU0MsZ0JBQWdCLENBQUM7RUFDdENDLFNBQVNBLENBQUEsRUFBRztJQUNSO0lBQ0EsSUFBSUMsTUFBTSxDQUFDQyxJQUFJLENBQUMsSUFBSSxDQUFDQyxJQUFJLENBQUMsQ0FBQ0MsTUFBTSxLQUFLLENBQUMsRUFBRTtNQUNyQyxJQUFJLENBQUNDLEdBQUcsQ0FBQyxRQUFRLENBQUMsQ0FBQ0MsR0FBRyxDQUFDLFNBQVMsRUFBRSxHQUFHLENBQUM7SUFDMUM7RUFDSjtFQUVBLE1BQU1DLE9BQU9BLENBQUEsRUFBRztJQUNaO0lBQ0EsSUFBSSxJQUFJLENBQUNDLElBQUksQ0FBQ0MsV0FBVyxFQUFFO01BQ3ZCLElBQUksQ0FBQ04sSUFBSSxHQUFHLE1BQU0sSUFBSSxDQUFDTyxVQUFVLENBQUMsQ0FBQztJQUN2QyxDQUFDLE1BQU0sSUFBSSxJQUFJLENBQUNGLElBQUksQ0FBQ0csT0FBTyxJQUFJLElBQUksQ0FBQ0gsSUFBSSxDQUFDSSxJQUFJLEVBQUU7TUFDNUM7TUFDQSxJQUFJLENBQUNULElBQUksR0FBRztRQUNSUSxPQUFPLEVBQUUsSUFBSSxDQUFDSCxJQUFJLENBQUNHLE9BQU87UUFDMUJDLElBQUksRUFBRSxJQUFJLENB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
|