From 679c3fb3a6bbfcd8ced21a6152cc7d6e33644a26 Mon Sep 17 00:00:00 2001 From: "Janus C. H. Knudsen" Date: Wed, 14 Jan 2026 16:53:42 +0100 Subject: [PATCH] Refactor employee table and row components Migrates custom table components to generic data table Improves consistency in table and row implementations Removes legacy custom table elements in favor of more flexible data table approach --- .../EmployeeDetailSalary/Default.cshtml | 28 +- .../Components/EmployeeRow/Default.cshtml | 22 +- .../Components/EmployeeTable/Default.cshtml | 24 +- .../wwwroot/css/components.css | 59 + .../wwwroot/css/employees.css | 152 +- PlanTempus.Application/wwwroot/js/app.js | 2226 +++++++++-------- .../wwwroot/ts/modules/employees.ts | 2 +- 7 files changed, 1257 insertions(+), 1256 deletions(-) diff --git a/PlanTempus.Application/Features/Employees/Components/EmployeeDetailSalary/Default.cshtml b/PlanTempus.Application/Features/Employees/Components/EmployeeDetailSalary/Default.cshtml index 074f145..ef42ff4 100644 --- a/PlanTempus.Application/Features/Employees/Components/EmployeeDetailSalary/Default.cshtml +++ b/PlanTempus.Application/Features/Employees/Components/EmployeeDetailSalary/Default.cshtml @@ -89,23 +89,23 @@ @Model.LabelSalaryHistory - - - @Model.LabelPeriod - @Model.LabelGrossSalary - - - +
+ + + @Model.LabelPeriod + @Model.LabelGrossSalary + + @foreach (var item in Model.SalaryHistory) { - - @item.Period - @item.GrossSalary - - + + @item.Period + @item.GrossSalary + + } - - + +
diff --git a/PlanTempus.Application/Features/Employees/Components/EmployeeRow/Default.cshtml b/PlanTempus.Application/Features/Employees/Components/EmployeeRow/Default.cshtml index d453a45..b443d5e 100644 --- a/PlanTempus.Application/Features/Employees/Components/EmployeeRow/Default.cshtml +++ b/PlanTempus.Application/Features/Employees/Components/EmployeeRow/Default.cshtml @@ -1,7 +1,7 @@ @model PlanTempus.Application.Features.Employees.Components.EmployeeRowViewModel - - + + @Model.Initials @@ -9,17 +9,17 @@ @Model.Email - - + + @Model.RoleText - - + + @Model.StatusText - - @Model.LastActive - + + @Model.LastActive + - - + + diff --git a/PlanTempus.Application/Features/Employees/Components/EmployeeTable/Default.cshtml b/PlanTempus.Application/Features/Employees/Components/EmployeeTable/Default.cshtml index b0fbdaf..f0b3e3e 100644 --- a/PlanTempus.Application/Features/Employees/Components/EmployeeTable/Default.cshtml +++ b/PlanTempus.Application/Features/Employees/Components/EmployeeTable/Default.cshtml @@ -14,21 +14,19 @@ - - - - @Model.ColumnUser - @Model.ColumnRole - @Model.ColumnStatus - @Model.ColumnLastActive - - - - +
+ + + @Model.ColumnUser + @Model.ColumnRole + @Model.ColumnStatus + @Model.ColumnLastActive + + @foreach (var employeeKey in Model.EmployeeKeys) { @await Component.InvokeAsync("EmployeeRow", employeeKey) } - - + +
diff --git a/PlanTempus.Application/wwwroot/css/components.css b/PlanTempus.Application/wwwroot/css/components.css index 613483e..07d5bc9 100644 --- a/PlanTempus.Application/wwwroot/css/components.css +++ b/PlanTempus.Application/wwwroot/css/components.css @@ -99,6 +99,65 @@ swp-icon-container { flex-shrink: 0; } +/* =========================================== + DATA TABLE (Generic Grid + Subgrid) + grid-template-columns defineres i feature CSS + =========================================== */ +swp-data-table { + display: grid; + + swp-data-table-header { + display: grid; + grid-column: 1 / -1; + grid-template-columns: subgrid; + background: var(--color-background-alt); + + swp-data-table-cell { + font-size: var(--font-size-xs); + font-weight: var(--font-weight-semibold); + text-transform: uppercase; + letter-spacing: 0.5px; + color: var(--color-text-secondary); + padding: var(--spacing-4); + } + } + + swp-data-table-row { + display: grid; + grid-column: 1 / -1; + grid-template-columns: subgrid; + align-items: center; + border-bottom: 1px solid var(--color-border); + transition: background var(--transition-fast); + + &:last-child { + border-bottom: none; + } + + &:hover { + background: var(--color-background-hover); + } + } + + swp-data-table-cell { + padding: var(--spacing-4); + font-size: var(--font-size-base); + color: var(--color-text); + + &.mono { + font-family: var(--font-mono); + } + + &.muted { + color: var(--color-text-muted); + } + + &.right { + text-align: right; + } + } +} + /* =========================================== BUTTONS (swp-btn) =========================================== */ diff --git a/PlanTempus.Application/wwwroot/css/employees.css b/PlanTempus.Application/wwwroot/css/employees.css index 40dfe3b..99c6993 100644 --- a/PlanTempus.Application/wwwroot/css/employees.css +++ b/PlanTempus.Application/wwwroot/css/employees.css @@ -56,7 +56,7 @@ swp-users-progress { } /* =========================================== - EMPLOYEE TABLE (Grid + Subgrid) + EMPLOYEE TABLE (uses swp-data-table from components.css) =========================================== */ swp-employee-table-card { display: block; @@ -66,61 +66,26 @@ swp-employee-table-card { overflow: hidden; } -swp-employee-table { - display: grid; +.employees-list swp-data-table { grid-template-columns: minmax(220px, 1fr) 120px 140px 120px 40px; - - swp-employee-table-header { - display: grid; - grid-column: 1 / -1; - grid-template-columns: subgrid; - background: var(--color-background-alt); - padding: 0 var(--spacing-10); - - swp-employee-cell { - font-size: var(--font-size-xs); - font-weight: var(--font-weight-semibold); - text-transform: uppercase; - letter-spacing: 0.5px; - color: var(--color-text-secondary); - padding-top: var(--spacing-5); - padding-bottom: var(--spacing-5); - } - } - - swp-employee-table-body { - display: grid; - grid-column: 1 / -1; - grid-template-columns: subgrid; - - swp-employee-row { - cursor: pointer; - - &:hover { - background: var(--color-background-hover); - } - } - } } -swp-employee-row { - display: grid; - grid-column: 1 / -1; - grid-template-columns: subgrid; - align-items: center; +.employees-list swp-data-table-header, +.employees-list swp-data-table-row { padding: 0 var(--spacing-10); - border-bottom: 1px solid var(--color-border); - transition: background var(--transition-fast); - - &:last-child { - border-bottom: none; - } } -swp-employee-cell { +.employees-list swp-data-table-header swp-data-table-cell { + padding-top: var(--spacing-5); + padding-bottom: var(--spacing-5); +} + +.employees-list swp-data-table-row { + cursor: pointer; +} + +.employees-list swp-data-table-cell { padding: var(--spacing-5) 0; - font-size: var(--font-size-base); - color: var(--color-text); &:last-child { display: flex; @@ -696,77 +661,40 @@ swp-notes-area { } /* =========================================== - SALARY TABLE (Grid + Subgrid) + SALARY TABLE (uses swp-data-table from components.css) =========================================== */ -swp-salary-table { - display: grid; +.salary-history swp-data-table { grid-template-columns: 1fr 120px 60px; +} - swp-salary-table-header { - display: grid; - grid-column: 1 / -1; - grid-template-columns: subgrid; - border-bottom: 1px solid var(--color-border); +.salary-history swp-data-table-header { + background: transparent; + border-bottom: 1px solid var(--color-border); +} - swp-salary-table-cell { - font-size: var(--font-size-xs); - font-weight: var(--font-weight-semibold); - text-transform: uppercase; - letter-spacing: 0.5px; - color: var(--color-text-secondary); - } +.salary-history swp-data-table-row { + cursor: pointer; + + &:hover swp-data-table-cell i { + color: var(--color-teal); + } +} + +.salary-history swp-data-table-cell { + padding: var(--spacing-4) var(--spacing-2); + + &:first-child { + padding-left: 0; } - swp-salary-table-body { - display: grid; - grid-column: 1 / -1; - grid-template-columns: subgrid; + &:last-child { + padding-right: 0; + text-align: right; } - swp-salary-table-row { - display: grid; - grid-column: 1 / -1; - grid-template-columns: subgrid; - align-items: center; - border-bottom: 1px solid var(--color-border); - cursor: pointer; - transition: background var(--transition-fast); - - &:last-child { - border-bottom: none; - } - - &:hover { - background: var(--color-background-hover); - - swp-salary-table-cell i { - color: var(--color-teal); - } - } - } - - swp-salary-table-cell { - padding: var(--spacing-4) var(--spacing-2); - font-size: var(--font-size-base); - color: var(--color-text); - - &:first-child { - padding-left: 0; - } - - &:last-child { - padding-right: 0; - text-align: right; - } - - &.mono { - font-family: var(--font-mono); - } - - i { - color: var(--color-text-muted); - font-size: 16px; - } + i { + color: var(--color-text-muted); + font-size: 16px; } } diff --git a/PlanTempus.Application/wwwroot/js/app.js b/PlanTempus.Application/wwwroot/js/app.js index 239ccf5..d554ee1 100644 --- a/PlanTempus.Application/wwwroot/js/app.js +++ b/PlanTempus.Application/wwwroot/js/app.js @@ -1,1160 +1,1176 @@ -"use strict"; -(() => { - // wwwroot/ts/modules/sidebar.ts - var SidebarController = class { - constructor() { - this.menuToggle = null; - this.appLayout = null; - this.menuTooltip = null; - this.menuToggle = document.getElementById("menuToggle"); - this.appLayout = document.querySelector("swp-app-layout"); - this.menuTooltip = document.getElementById("menuTooltip"); - this.setupListeners(); - this.setupTooltips(); - this.restoreState(); - } - /** - * Check if sidebar is collapsed - */ - get isCollapsed() { - return this.appLayout?.classList.contains("menu-collapsed") ?? false; - } - /** - * Toggle sidebar collapsed state - */ - toggle() { - if (!this.appLayout) return; - this.appLayout.classList.toggle("menu-collapsed"); - localStorage.setItem("sidebar-collapsed", String(this.isCollapsed)); - } - /** - * Collapse the sidebar - */ - collapse() { - this.appLayout?.classList.add("menu-collapsed"); - localStorage.setItem("sidebar-collapsed", "true"); - } - /** - * Expand the sidebar - */ - expand() { - this.appLayout?.classList.remove("menu-collapsed"); - localStorage.setItem("sidebar-collapsed", "false"); - } - setupListeners() { - this.menuToggle?.addEventListener("click", () => this.toggle()); - } - setupTooltips() { - if (!this.menuTooltip) return; - const menuItems = document.querySelectorAll("swp-side-menu-item[data-tooltip]"); - menuItems.forEach((item) => { - item.addEventListener("mouseenter", () => this.showTooltip(item)); - item.addEventListener("mouseleave", () => this.hideTooltip()); - }); - } - showTooltip(item) { - if (!this.isCollapsed || !this.menuTooltip) return; - const rect = item.getBoundingClientRect(); - const tooltipText = item.dataset.tooltip; - if (!tooltipText) return; - this.menuTooltip.textContent = tooltipText; - this.menuTooltip.style.left = `${rect.right + 8}px`; - this.menuTooltip.style.top = `${rect.top + rect.height / 2}px`; - this.menuTooltip.style.transform = "translateY(-50%)"; - this.menuTooltip.showPopover(); - } - hideTooltip() { - this.menuTooltip?.hidePopover(); - } - restoreState() { - if (!this.appLayout) return; - if (localStorage.getItem("sidebar-collapsed") === "true") { - this.appLayout.classList.add("menu-collapsed"); - } - } - }; +var __defProp = Object.defineProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); - // wwwroot/ts/modules/drawers.ts - var DrawerController = class { - constructor() { - this.profileDrawer = null; - this.notificationDrawer = null; - this.todoDrawer = null; - this.newTodoDrawer = null; - this.overlay = null; - this.activeDrawer = null; - this.activeGenericDrawer = null; - this.profileDrawer = document.getElementById("profileDrawer"); - this.notificationDrawer = document.getElementById("notificationDrawer"); - this.todoDrawer = document.getElementById("todoDrawer"); - this.newTodoDrawer = document.getElementById("newTodoDrawer"); - this.overlay = document.getElementById("drawerOverlay"); - this.setupListeners(); - this.setupGenericDrawers(); +// wwwroot/ts/modules/sidebar.ts +var _SidebarController = class _SidebarController { + constructor() { + this.menuToggle = null; + this.appLayout = null; + this.menuTooltip = null; + this.menuToggle = document.getElementById("menuToggle"); + this.appLayout = document.querySelector("swp-app-layout"); + this.menuTooltip = document.getElementById("menuTooltip"); + this.setupListeners(); + this.setupTooltips(); + this.restoreState(); + } + /** + * Check if sidebar is collapsed + */ + get isCollapsed() { + return this.appLayout?.classList.contains("menu-collapsed") ?? false; + } + /** + * Toggle sidebar collapsed state + */ + toggle() { + if (!this.appLayout) return; + this.appLayout.classList.toggle("menu-collapsed"); + localStorage.setItem("sidebar-collapsed", String(this.isCollapsed)); + } + /** + * Collapse the sidebar + */ + collapse() { + this.appLayout?.classList.add("menu-collapsed"); + localStorage.setItem("sidebar-collapsed", "true"); + } + /** + * Expand the sidebar + */ + expand() { + this.appLayout?.classList.remove("menu-collapsed"); + localStorage.setItem("sidebar-collapsed", "false"); + } + setupListeners() { + this.menuToggle?.addEventListener("click", () => this.toggle()); + } + setupTooltips() { + if (!this.menuTooltip) return; + const menuItems = document.querySelectorAll("swp-side-menu-item[data-tooltip]"); + menuItems.forEach((item) => { + item.addEventListener("mouseenter", () => this.showTooltip(item)); + item.addEventListener("mouseleave", () => this.hideTooltip()); + }); + } + showTooltip(item) { + if (!this.isCollapsed || !this.menuTooltip) return; + const rect = item.getBoundingClientRect(); + const tooltipText = item.dataset.tooltip; + if (!tooltipText) return; + this.menuTooltip.textContent = tooltipText; + this.menuTooltip.style.left = `${rect.right + 8}px`; + this.menuTooltip.style.top = `${rect.top + rect.height / 2}px`; + this.menuTooltip.style.transform = "translateY(-50%)"; + this.menuTooltip.showPopover(); + } + hideTooltip() { + this.menuTooltip?.hidePopover(); + } + restoreState() { + if (!this.appLayout) return; + if (localStorage.getItem("sidebar-collapsed") === "true") { + this.appLayout.classList.add("menu-collapsed"); } - /** - * Get currently active drawer name - */ - get active() { - return this.activeDrawer; + } +}; +__name(_SidebarController, "SidebarController"); +var SidebarController = _SidebarController; + +// wwwroot/ts/modules/drawers.ts +var _DrawerController = class _DrawerController { + constructor() { + this.profileDrawer = null; + this.notificationDrawer = null; + this.todoDrawer = null; + this.newTodoDrawer = null; + this.overlay = null; + this.activeDrawer = null; + this.activeGenericDrawer = null; + this.profileDrawer = document.getElementById("profileDrawer"); + this.notificationDrawer = document.getElementById("notificationDrawer"); + this.todoDrawer = document.getElementById("todoDrawer"); + this.newTodoDrawer = document.getElementById("newTodoDrawer"); + this.overlay = document.getElementById("drawerOverlay"); + this.setupListeners(); + this.setupGenericDrawers(); + } + /** + * Get currently active drawer name + */ + get active() { + return this.activeDrawer; + } + /** + * Open a drawer by name + */ + open(name) { + this.closeAll(); + const drawer = this.getDrawer(name); + if (drawer && this.overlay) { + drawer.classList.add("active"); + this.overlay.classList.add("active"); + document.body.style.overflow = "hidden"; + this.activeDrawer = name; } - /** - * Open a drawer by name - */ - open(name) { - this.closeAll(); - const drawer = this.getDrawer(name); - if (drawer && this.overlay) { - drawer.classList.add("active"); - this.overlay.classList.add("active"); - document.body.style.overflow = "hidden"; - this.activeDrawer = name; - } - } - /** - * Close a specific drawer - */ - close(name) { - const drawer = this.getDrawer(name); - drawer?.classList.remove("active"); - if (this.overlay && !document.querySelector('.active[class*="drawer"]')) { - this.overlay.classList.remove("active"); - document.body.style.overflow = ""; - } - if (this.activeDrawer === name) { - this.activeDrawer = null; - } - } - /** - * Close all drawers - */ - closeAll() { - [this.profileDrawer, this.notificationDrawer, this.todoDrawer, this.newTodoDrawer].forEach((drawer) => drawer?.classList.remove("active")); - this.closeGenericDrawer(); - this.overlay?.classList.remove("active"); + } + /** + * Close a specific drawer + */ + close(name) { + const drawer = this.getDrawer(name); + drawer?.classList.remove("active"); + if (this.overlay && !document.querySelector('.active[class*="drawer"]')) { + this.overlay.classList.remove("active"); document.body.style.overflow = ""; + } + if (this.activeDrawer === name) { this.activeDrawer = null; } - /** - * Open a generic drawer by ID - */ - openGenericDrawer(drawerId) { - this.closeAll(); - const drawer = document.getElementById(drawerId); - if (drawer && this.overlay) { - drawer.classList.add("open"); - this.overlay.classList.add("active"); - document.body.style.overflow = "hidden"; - this.activeGenericDrawer = drawer; + } + /** + * Close all drawers + */ + closeAll() { + [this.profileDrawer, this.notificationDrawer, this.todoDrawer, this.newTodoDrawer].forEach((drawer) => drawer?.classList.remove("active")); + this.closeGenericDrawer(); + this.overlay?.classList.remove("active"); + document.body.style.overflow = ""; + this.activeDrawer = null; + } + /** + * Open a generic drawer by ID + */ + openGenericDrawer(drawerId) { + this.closeAll(); + const drawer = document.getElementById(drawerId); + if (drawer && this.overlay) { + drawer.classList.add("open"); + this.overlay.classList.add("active"); + document.body.style.overflow = "hidden"; + this.activeGenericDrawer = drawer; + } + } + /** + * Close the currently open generic drawer + */ + closeGenericDrawer() { + this.activeGenericDrawer?.classList.remove("open"); + this.activeGenericDrawer = null; + } + /** + * Open profile drawer + */ + openProfile() { + this.open("profile"); + } + /** + * Open notification drawer + */ + openNotification() { + this.open("notification"); + } + /** + * Open todo drawer (slides on top of profile) + */ + openTodo() { + this.todoDrawer?.classList.add("active"); + } + /** + * Close todo drawer + */ + closeTodo() { + this.todoDrawer?.classList.remove("active"); + this.closeNewTodo(); + } + /** + * Open new todo drawer + */ + openNewTodo() { + this.newTodoDrawer?.classList.add("active"); + } + /** + * Close new todo drawer + */ + closeNewTodo() { + this.newTodoDrawer?.classList.remove("active"); + } + /** + * Mark all notifications as read + */ + markAllNotificationsRead() { + if (!this.notificationDrawer) return; + const unreadItems = this.notificationDrawer.querySelectorAll( + 'swp-notification-item[data-unread="true"]' + ); + unreadItems.forEach((item) => item.removeAttribute("data-unread")); + const badge = document.querySelector("swp-notification-badge"); + if (badge) { + badge.style.display = "none"; + } + } + getDrawer(name) { + switch (name) { + case "profile": + return this.profileDrawer; + case "notification": + return this.notificationDrawer; + case "todo": + return this.todoDrawer; + case "newTodo": + return this.newTodoDrawer; + } + } + setupListeners() { + document.getElementById("profileTrigger")?.addEventListener("click", () => this.openProfile()); + document.getElementById("drawerClose")?.addEventListener("click", () => this.close("profile")); + document.getElementById("notificationsBtn")?.addEventListener("click", () => this.openNotification()); + document.getElementById("notificationDrawerClose")?.addEventListener("click", () => this.close("notification")); + document.getElementById("markAllRead")?.addEventListener("click", () => this.markAllNotificationsRead()); + document.getElementById("openTodoDrawer")?.addEventListener("click", () => this.openTodo()); + document.getElementById("todoDrawerBack")?.addEventListener("click", () => this.closeTodo()); + document.getElementById("addTodoBtn")?.addEventListener("click", () => this.openNewTodo()); + document.getElementById("newTodoDrawerBack")?.addEventListener("click", () => this.closeNewTodo()); + document.getElementById("cancelNewTodo")?.addEventListener("click", () => this.closeNewTodo()); + document.getElementById("saveNewTodo")?.addEventListener("click", () => this.closeNewTodo()); + this.overlay?.addEventListener("click", () => this.closeAll()); + document.addEventListener("keydown", (e) => { + if (e.key === "Escape") this.closeAll(); + }); + this.todoDrawer?.addEventListener("click", (e) => this.handleTodoClick(e)); + document.addEventListener("click", (e) => this.handleVisibilityClick(e)); + } + handleTodoClick(e) { + const target = e.target; + const todoItem = target.closest("swp-todo-item"); + const checkbox = target.closest("swp-todo-checkbox"); + if (checkbox && todoItem) { + const isCompleted = todoItem.dataset.completed === "true"; + if (isCompleted) { + todoItem.removeAttribute("data-completed"); + } else { + todoItem.dataset.completed = "true"; } } - /** - * Close the currently open generic drawer - */ - closeGenericDrawer() { - this.activeGenericDrawer?.classList.remove("open"); - this.activeGenericDrawer = null; + const sectionHeader = target.closest("swp-todo-section-header"); + if (sectionHeader) { + const section = sectionHeader.closest("swp-todo-section"); + section?.classList.toggle("collapsed"); } - /** - * Open profile drawer - */ - openProfile() { - this.open("profile"); + } + handleVisibilityClick(e) { + const target = e.target; + const option = target.closest("swp-visibility-option"); + if (option) { + document.querySelectorAll("swp-visibility-option").forEach((o) => o.classList.remove("active")); + option.classList.add("active"); } - /** - * Open notification drawer - */ - openNotification() { - this.open("notification"); - } - /** - * Open todo drawer (slides on top of profile) - */ - openTodo() { - this.todoDrawer?.classList.add("active"); - } - /** - * Close todo drawer - */ - closeTodo() { - this.todoDrawer?.classList.remove("active"); - this.closeNewTodo(); - } - /** - * Open new todo drawer - */ - openNewTodo() { - this.newTodoDrawer?.classList.add("active"); - } - /** - * Close new todo drawer - */ - closeNewTodo() { - this.newTodoDrawer?.classList.remove("active"); - } - /** - * Mark all notifications as read - */ - markAllNotificationsRead() { - if (!this.notificationDrawer) return; - const unreadItems = this.notificationDrawer.querySelectorAll( - 'swp-notification-item[data-unread="true"]' - ); - unreadItems.forEach((item) => item.removeAttribute("data-unread")); - const badge = document.querySelector("swp-notification-badge"); - if (badge) { - badge.style.display = "none"; - } - } - getDrawer(name) { - switch (name) { - case "profile": - return this.profileDrawer; - case "notification": - return this.notificationDrawer; - case "todo": - return this.todoDrawer; - case "newTodo": - return this.newTodoDrawer; - } - } - setupListeners() { - document.getElementById("profileTrigger")?.addEventListener("click", () => this.openProfile()); - document.getElementById("drawerClose")?.addEventListener("click", () => this.close("profile")); - document.getElementById("notificationsBtn")?.addEventListener("click", () => this.openNotification()); - document.getElementById("notificationDrawerClose")?.addEventListener("click", () => this.close("notification")); - document.getElementById("markAllRead")?.addEventListener("click", () => this.markAllNotificationsRead()); - document.getElementById("openTodoDrawer")?.addEventListener("click", () => this.openTodo()); - document.getElementById("todoDrawerBack")?.addEventListener("click", () => this.closeTodo()); - document.getElementById("addTodoBtn")?.addEventListener("click", () => this.openNewTodo()); - document.getElementById("newTodoDrawerBack")?.addEventListener("click", () => this.closeNewTodo()); - document.getElementById("cancelNewTodo")?.addEventListener("click", () => this.closeNewTodo()); - document.getElementById("saveNewTodo")?.addEventListener("click", () => this.closeNewTodo()); - this.overlay?.addEventListener("click", () => this.closeAll()); - document.addEventListener("keydown", (e) => { - if (e.key === "Escape") this.closeAll(); - }); - this.todoDrawer?.addEventListener("click", (e) => this.handleTodoClick(e)); - document.addEventListener("click", (e) => this.handleVisibilityClick(e)); - } - handleTodoClick(e) { + } + /** + * Setup generic drawer triggers and close buttons + * Uses data-drawer-trigger="drawer-id" and data-drawer-close attributes + */ + setupGenericDrawers() { + document.addEventListener("click", (e) => { const target = e.target; - const todoItem = target.closest("swp-todo-item"); - const checkbox = target.closest("swp-todo-checkbox"); - if (checkbox && todoItem) { - const isCompleted = todoItem.dataset.completed === "true"; - if (isCompleted) { - todoItem.removeAttribute("data-completed"); - } else { - todoItem.dataset.completed = "true"; + const trigger = target.closest("[data-drawer-trigger]"); + if (trigger) { + const drawerId = trigger.dataset.drawerTrigger; + if (drawerId) { + this.openGenericDrawer(drawerId); } } - const sectionHeader = target.closest("swp-todo-section-header"); - if (sectionHeader) { - const section = sectionHeader.closest("swp-todo-section"); - section?.classList.toggle("collapsed"); - } - } - handleVisibilityClick(e) { + }); + document.addEventListener("click", (e) => { const target = e.target; - const option = target.closest("swp-visibility-option"); - if (option) { - document.querySelectorAll("swp-visibility-option").forEach((o) => o.classList.remove("active")); - option.classList.add("active"); - } - } - /** - * Setup generic drawer triggers and close buttons - * Uses data-drawer-trigger="drawer-id" and data-drawer-close attributes - */ - setupGenericDrawers() { - document.addEventListener("click", (e) => { - const target = e.target; - const trigger = target.closest("[data-drawer-trigger]"); - if (trigger) { - const drawerId = trigger.dataset.drawerTrigger; - if (drawerId) { - this.openGenericDrawer(drawerId); - } - } - }); - document.addEventListener("click", (e) => { - const target = e.target; - const closeBtn = target.closest("[data-drawer-close]"); - if (closeBtn) { - this.closeGenericDrawer(); - this.overlay?.classList.remove("active"); - document.body.style.overflow = ""; - } - }); - } - }; - - // wwwroot/ts/modules/theme.ts - var ThemeController = class _ThemeController { - static { - this.STORAGE_KEY = "theme-preference"; - } - static { - this.DARK_CLASS = "dark-mode"; - } - static { - this.LIGHT_CLASS = "light-mode"; - } - constructor() { - this.root = document.documentElement; - this.themeOptions = document.querySelectorAll("swp-theme-option"); - this.applyTheme(this.current); - this.updateUI(); - this.setupListeners(); - } - /** - * Get the current theme setting - */ - get current() { - const stored = localStorage.getItem(_ThemeController.STORAGE_KEY); - if (stored === "dark" || stored === "light" || stored === "system") { - return stored; - } - return "system"; - } - /** - * Check if dark mode is currently active - */ - get isDark() { - return this.root.classList.contains(_ThemeController.DARK_CLASS) || this.systemPrefersDark && !this.root.classList.contains(_ThemeController.LIGHT_CLASS); - } - /** - * Check if system prefers dark mode - */ - get systemPrefersDark() { - return window.matchMedia("(prefers-color-scheme: dark)").matches; - } - /** - * Set theme and persist preference - */ - set(theme) { - localStorage.setItem(_ThemeController.STORAGE_KEY, theme); - this.applyTheme(theme); - this.updateUI(); - } - /** - * Toggle between light and dark themes - */ - toggle() { - this.set(this.isDark ? "light" : "dark"); - } - applyTheme(theme) { - this.root.classList.remove(_ThemeController.DARK_CLASS, _ThemeController.LIGHT_CLASS); - if (theme === "dark") { - this.root.classList.add(_ThemeController.DARK_CLASS); - } else if (theme === "light") { - this.root.classList.add(_ThemeController.LIGHT_CLASS); - } - } - updateUI() { - if (!this.themeOptions) return; - const darkActive = this.isDark; - this.themeOptions.forEach((option) => { - const theme = option.dataset.theme; - const isActive = theme === "dark" && darkActive || theme === "light" && !darkActive; - option.classList.toggle("active", isActive); - }); - } - setupListeners() { - this.themeOptions.forEach((option) => { - option.addEventListener("click", (e) => this.handleOptionClick(e)); - }); - window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change", () => this.handleSystemChange()); - } - handleOptionClick(e) { - const target = e.target; - const option = target.closest("swp-theme-option"); - if (option) { - const theme = option.dataset.theme; - if (theme) { - this.set(theme); - } - } - } - handleSystemChange() { - if (this.current === "system") { - this.updateUI(); - } - } - }; - - // wwwroot/ts/modules/search.ts - var SearchController = class { - constructor() { - this.input = null; - this.container = null; - this.input = document.getElementById("globalSearch"); - this.container = document.querySelector("swp-topbar-search"); - this.setupListeners(); - } - /** - * Get current search value - */ - get value() { - return this.input?.value ?? ""; - } - /** - * Set search value - */ - set value(val) { - if (this.input) { - this.input.value = val; - } - } - /** - * Focus the search input - */ - focus() { - this.input?.focus(); - } - /** - * Blur the search input - */ - blur() { - this.input?.blur(); - } - /** - * Clear the search input - */ - clear() { - this.value = ""; - } - setupListeners() { - document.addEventListener("keydown", (e) => this.handleKeyboard(e)); - if (this.input) { - this.input.addEventListener("input", (e) => this.handleInput(e)); - const form = this.input.closest("form"); - form?.addEventListener("submit", (e) => this.handleSubmit(e)); - } - } - handleKeyboard(e) { - if ((e.metaKey || e.ctrlKey) && e.key === "k") { - e.preventDefault(); - this.focus(); - return; - } - if (e.key === "Escape" && document.activeElement === this.input) { - this.blur(); - } - } - handleInput(e) { - const target = e.target; - const query = target.value.trim(); - document.dispatchEvent(new CustomEvent("app:search", { - detail: { query }, - bubbles: true - })); - } - handleSubmit(e) { - e.preventDefault(); - const query = this.value.trim(); - if (!query) return; - document.dispatchEvent(new CustomEvent("app:search-submit", { - detail: { query }, - bubbles: true - })); - } - }; - - // wwwroot/ts/modules/lockscreen.ts - var LockScreenController = class _LockScreenController { - constructor(drawers) { - // Demo PIN - this.lockScreen = null; - this.pinInput = null; - this.pinKeypad = null; - this.lockTimeEl = null; - this.pinDigits = null; - this.currentPin = ""; - this.drawers = null; - this.drawers = drawers ?? null; - this.lockScreen = document.getElementById("lockScreen"); - this.pinInput = document.getElementById("pinInput"); - this.pinKeypad = document.getElementById("pinKeypad"); - this.lockTimeEl = document.getElementById("lockTime"); - this.pinDigits = this.pinInput?.querySelectorAll("swp-pin-digit") ?? null; - this.setupListeners(); - } - static { - this.CORRECT_PIN = "1234"; - } - /** - * Check if lock screen is active - */ - get isActive() { - return this.lockScreen?.classList.contains("active") ?? false; - } - /** - * Show the lock screen - */ - show() { - this.drawers?.closeAll(); - if (this.lockScreen) { - this.lockScreen.classList.add("active"); - document.body.style.overflow = "hidden"; - } - this.currentPin = ""; - this.updateDisplay(); - if (this.lockTimeEl) { - this.lockTimeEl.textContent = `L\xE5st kl. ${this.formatTime()}`; - } - } - /** - * Hide the lock screen - */ - hide() { - if (this.lockScreen) { - this.lockScreen.classList.remove("active"); + const closeBtn = target.closest("[data-drawer-close]"); + if (closeBtn) { + this.closeGenericDrawer(); + this.overlay?.classList.remove("active"); document.body.style.overflow = ""; } - this.currentPin = ""; - this.updateDisplay(); - } - formatTime() { - const now = /* @__PURE__ */ new Date(); - const hours = now.getHours().toString().padStart(2, "0"); - const minutes = now.getMinutes().toString().padStart(2, "0"); - return `${hours}:${minutes}`; - } - updateDisplay() { - if (!this.pinDigits) return; - this.pinDigits.forEach((digit, index) => { - digit.classList.remove("filled", "error"); - if (index < this.currentPin.length) { - digit.textContent = "\u2022"; - digit.classList.add("filled"); - } else { - digit.textContent = ""; - } - }); - } - showError() { - if (!this.pinDigits) return; - this.pinDigits.forEach((digit) => digit.classList.add("error")); - this.pinInput?.classList.add("shake"); - setTimeout(() => { - this.currentPin = ""; - this.updateDisplay(); - this.pinInput?.classList.remove("shake"); - }, 500); - } - verify() { - if (this.currentPin === _LockScreenController.CORRECT_PIN) { - this.hide(); - } else { - this.showError(); - } - } - addDigit(digit) { - if (this.currentPin.length >= 4) return; - this.currentPin += digit; - this.updateDisplay(); - if (this.currentPin.length === 4) { - setTimeout(() => this.verify(), 200); - } - } - removeDigit() { - if (this.currentPin.length === 0) return; - this.currentPin = this.currentPin.slice(0, -1); - this.updateDisplay(); - } - clearPin() { - this.currentPin = ""; - this.updateDisplay(); - } - setupListeners() { - this.pinKeypad?.addEventListener("click", (e) => this.handleKeypadClick(e)); - document.addEventListener("keydown", (e) => this.handleKeyboard(e)); - document.querySelector("swp-side-menu-action.lock")?.addEventListener("click", () => this.show()); - } - handleKeypadClick(e) { - const target = e.target; - const key = target.closest("swp-pin-key"); - if (!key) return; - const digit = key.dataset.digit; - const action = key.dataset.action; - if (digit) { - this.addDigit(digit); - } else if (action === "backspace") { - this.removeDigit(); - } else if (action === "clear") { - this.clearPin(); - } - } - handleKeyboard(e) { - if (!this.isActive) return; - e.preventDefault(); - if (e.key >= "0" && e.key <= "9") { - this.addDigit(e.key); - } else if (e.key === "Backspace") { - this.removeDigit(); - } else if (e.key === "Escape") { - this.clearPin(); - } - } - }; + }); + } +}; +__name(_DrawerController, "DrawerController"); +var DrawerController = _DrawerController; - // wwwroot/ts/modules/cash.ts - var CashController = class { - constructor() { - // Base values (from system - would come from server in real app) - this.startBalance = 2e3; - this.cashSales = 3540; - this.setupTabs(); - this.setupCashCalculation(); - this.setupCheckboxSelection(); - this.setupApprovalCheckbox(); - this.setupDateFilters(); - this.setupRowToggle(); - this.setupDraftRowClick(); +// wwwroot/ts/modules/theme.ts +var _ThemeController = class _ThemeController { + constructor() { + this.root = document.documentElement; + this.themeOptions = document.querySelectorAll("swp-theme-option"); + this.applyTheme(this.current); + this.updateUI(); + this.setupListeners(); + } + /** + * Get the current theme setting + */ + get current() { + const stored = localStorage.getItem(_ThemeController.STORAGE_KEY); + if (stored === "dark" || stored === "light" || stored === "system") { + return stored; } - /** - * Setup tab switching functionality - */ - setupTabs() { - const tabs = document.querySelectorAll("swp-tab[data-tab]"); - tabs.forEach((tab) => { - tab.addEventListener("click", () => { - const targetTab = tab.dataset.tab; - if (targetTab) { - this.switchToTab(targetTab); - } - }); - }); + return "system"; + } + /** + * Check if dark mode is currently active + */ + get isDark() { + return this.root.classList.contains(_ThemeController.DARK_CLASS) || this.systemPrefersDark && !this.root.classList.contains(_ThemeController.LIGHT_CLASS); + } + /** + * Check if system prefers dark mode + */ + get systemPrefersDark() { + return window.matchMedia("(prefers-color-scheme: dark)").matches; + } + /** + * Set theme and persist preference + */ + set(theme) { + localStorage.setItem(_ThemeController.STORAGE_KEY, theme); + this.applyTheme(theme); + this.updateUI(); + } + /** + * Toggle between light and dark themes + */ + toggle() { + this.set(this.isDark ? "light" : "dark"); + } + applyTheme(theme) { + this.root.classList.remove(_ThemeController.DARK_CLASS, _ThemeController.LIGHT_CLASS); + if (theme === "dark") { + this.root.classList.add(_ThemeController.DARK_CLASS); + } else if (theme === "light") { + this.root.classList.add(_ThemeController.LIGHT_CLASS); } - /** - * Switch to a specific tab by name - */ - switchToTab(targetTab) { - const tabs = document.querySelectorAll("swp-tab[data-tab]"); - const contents = document.querySelectorAll("swp-tab-content[data-tab]"); - const statsBars = document.querySelectorAll("swp-cash-stats[data-for-tab]"); - tabs.forEach((t) => { - if (t.dataset.tab === targetTab) { - t.classList.add("active"); - } else { - t.classList.remove("active"); - } - }); - contents.forEach((content) => { - if (content.dataset.tab === targetTab) { - content.classList.add("active"); - } else { - content.classList.remove("active"); - } - }); - statsBars.forEach((stats) => { - if (stats.dataset.forTab === targetTab) { - stats.classList.add("active"); - } else { - stats.classList.remove("active"); - } - }); - } - /** - * Setup cash calculation with real-time updates - */ - setupCashCalculation() { - const payoutsInput = document.getElementById("payouts"); - const toBankInput = document.getElementById("toBank"); - const actualCashInput = document.getElementById("actualCash"); - if (!payoutsInput || !toBankInput || !actualCashInput) return; - const calculate = () => this.calculateCash(payoutsInput, toBankInput, actualCashInput); - payoutsInput.addEventListener("input", calculate); - toBankInput.addEventListener("input", calculate); - actualCashInput.addEventListener("input", calculate); - calculate(); - } - /** - * Calculate expected cash and difference - */ - calculateCash(payoutsInput, toBankInput, actualCashInput) { - const payouts = this.parseNumber(payoutsInput.value); - const toBank = this.parseNumber(toBankInput.value); - const actual = this.parseNumber(actualCashInput.value); - const expectedCash = this.startBalance + this.cashSales - payouts - toBank; - const expectedElement = document.getElementById("expectedCash"); - if (expectedElement) { - expectedElement.textContent = this.formatNumber(expectedCash); + } + updateUI() { + if (!this.themeOptions) return; + const darkActive = this.isDark; + this.themeOptions.forEach((option) => { + const theme = option.dataset.theme; + const isActive = theme === "dark" && darkActive || theme === "light" && !darkActive; + option.classList.toggle("active", isActive); + }); + } + setupListeners() { + this.themeOptions.forEach((option) => { + option.addEventListener("click", (e) => this.handleOptionClick(e)); + }); + window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change", () => this.handleSystemChange()); + } + handleOptionClick(e) { + const target = e.target; + const option = target.closest("swp-theme-option"); + if (option) { + const theme = option.dataset.theme; + if (theme) { + this.set(theme); } - this.updateDifference(actual, expectedCash, actualCashInput.value); } - /** - * Update difference box with color coding - */ - updateDifference(actual, expected, rawValue) { - const box = document.getElementById("differenceBox"); - const value = document.getElementById("differenceValue"); - if (!box || !value) return; - const diff = actual - expected; - box.classList.remove("positive", "negative", "neutral"); - if (actual === 0 && rawValue === "") { - value.textContent = "\u2013 kr"; - box.classList.add("neutral"); - } else if (diff > 0) { - value.textContent = "+" + this.formatNumber(diff) + " kr"; - box.classList.add("positive"); - } else if (diff < 0) { - value.textContent = this.formatNumber(diff) + " kr"; - box.classList.add("negative"); + } + handleSystemChange() { + if (this.current === "system") { + this.updateUI(); + } + } +}; +__name(_ThemeController, "ThemeController"); +_ThemeController.STORAGE_KEY = "theme-preference"; +_ThemeController.DARK_CLASS = "dark-mode"; +_ThemeController.LIGHT_CLASS = "light-mode"; +var ThemeController = _ThemeController; + +// wwwroot/ts/modules/search.ts +var _SearchController = class _SearchController { + constructor() { + this.input = null; + this.container = null; + this.input = document.getElementById("globalSearch"); + this.container = document.querySelector("swp-topbar-search"); + this.setupListeners(); + } + /** + * Get current search value + */ + get value() { + return this.input?.value ?? ""; + } + /** + * Set search value + */ + set value(val) { + if (this.input) { + this.input.value = val; + } + } + /** + * Focus the search input + */ + focus() { + this.input?.focus(); + } + /** + * Blur the search input + */ + blur() { + this.input?.blur(); + } + /** + * Clear the search input + */ + clear() { + this.value = ""; + } + setupListeners() { + document.addEventListener("keydown", (e) => this.handleKeyboard(e)); + if (this.input) { + this.input.addEventListener("input", (e) => this.handleInput(e)); + const form = this.input.closest("form"); + form?.addEventListener("submit", (e) => this.handleSubmit(e)); + } + } + handleKeyboard(e) { + if ((e.metaKey || e.ctrlKey) && e.key === "k") { + e.preventDefault(); + this.focus(); + return; + } + if (e.key === "Escape" && document.activeElement === this.input) { + this.blur(); + } + } + handleInput(e) { + const target = e.target; + const query = target.value.trim(); + document.dispatchEvent(new CustomEvent("app:search", { + detail: { query }, + bubbles: true + })); + } + handleSubmit(e) { + e.preventDefault(); + const query = this.value.trim(); + if (!query) return; + document.dispatchEvent(new CustomEvent("app:search-submit", { + detail: { query }, + bubbles: true + })); + } +}; +__name(_SearchController, "SearchController"); +var SearchController = _SearchController; + +// wwwroot/ts/modules/lockscreen.ts +var _LockScreenController = class _LockScreenController { + constructor(drawers) { + // Demo PIN + this.lockScreen = null; + this.pinInput = null; + this.pinKeypad = null; + this.lockTimeEl = null; + this.pinDigits = null; + this.currentPin = ""; + this.drawers = null; + this.drawers = drawers ?? null; + this.lockScreen = document.getElementById("lockScreen"); + this.pinInput = document.getElementById("pinInput"); + this.pinKeypad = document.getElementById("pinKeypad"); + this.lockTimeEl = document.getElementById("lockTime"); + this.pinDigits = this.pinInput?.querySelectorAll("swp-pin-digit") ?? null; + this.setupListeners(); + } + /** + * Check if lock screen is active + */ + get isActive() { + return this.lockScreen?.classList.contains("active") ?? false; + } + /** + * Show the lock screen + */ + show() { + this.drawers?.closeAll(); + if (this.lockScreen) { + this.lockScreen.classList.add("active"); + document.body.style.overflow = "hidden"; + } + this.currentPin = ""; + this.updateDisplay(); + if (this.lockTimeEl) { + this.lockTimeEl.textContent = `L\xE5st kl. ${this.formatTime()}`; + } + } + /** + * Hide the lock screen + */ + hide() { + if (this.lockScreen) { + this.lockScreen.classList.remove("active"); + document.body.style.overflow = ""; + } + this.currentPin = ""; + this.updateDisplay(); + } + formatTime() { + const now = /* @__PURE__ */ new Date(); + const hours = now.getHours().toString().padStart(2, "0"); + const minutes = now.getMinutes().toString().padStart(2, "0"); + return `${hours}:${minutes}`; + } + updateDisplay() { + if (!this.pinDigits) return; + this.pinDigits.forEach((digit, index) => { + digit.classList.remove("filled", "error"); + if (index < this.currentPin.length) { + digit.textContent = "\u2022"; + digit.classList.add("filled"); } else { - value.textContent = "0,00 kr"; - box.classList.add("neutral"); + digit.textContent = ""; } + }); + } + showError() { + if (!this.pinDigits) return; + this.pinDigits.forEach((digit) => digit.classList.add("error")); + this.pinInput?.classList.add("shake"); + setTimeout(() => { + this.currentPin = ""; + this.updateDisplay(); + this.pinInput?.classList.remove("shake"); + }, 500); + } + verify() { + if (this.currentPin === _LockScreenController.CORRECT_PIN) { + this.hide(); + } else { + this.showError(); } - /** - * Setup checkbox selection for table rows - */ - setupCheckboxSelection() { - const selectAll = document.getElementById("selectAll"); - const rowCheckboxes = document.querySelectorAll(".row-select"); - const exportBtn = document.getElementById("exportBtn"); - const selectionCount = document.getElementById("selectionCount"); - if (!selectAll || !exportBtn || !selectionCount) return; - const updateSelection = () => { - const checked = document.querySelectorAll(".row-select:checked"); - const count = checked.length; - selectionCount.textContent = count === 0 ? "0 valgt" : `${count} valgt`; - exportBtn.disabled = count === 0; - selectAll.checked = count === rowCheckboxes.length && count > 0; - selectAll.indeterminate = count > 0 && count < rowCheckboxes.length; - }; - selectAll.addEventListener("change", () => { - rowCheckboxes.forEach((cb) => cb.checked = selectAll.checked); - updateSelection(); - }); - rowCheckboxes.forEach((cb) => { - cb.addEventListener("change", updateSelection); - cb.addEventListener("click", (e) => e.stopPropagation()); + } + addDigit(digit) { + if (this.currentPin.length >= 4) return; + this.currentPin += digit; + this.updateDisplay(); + if (this.currentPin.length === 4) { + setTimeout(() => this.verify(), 200); + } + } + removeDigit() { + if (this.currentPin.length === 0) return; + this.currentPin = this.currentPin.slice(0, -1); + this.updateDisplay(); + } + clearPin() { + this.currentPin = ""; + this.updateDisplay(); + } + setupListeners() { + this.pinKeypad?.addEventListener("click", (e) => this.handleKeypadClick(e)); + document.addEventListener("keydown", (e) => this.handleKeyboard(e)); + document.querySelector("swp-side-menu-action.lock")?.addEventListener("click", () => this.show()); + } + handleKeypadClick(e) { + const target = e.target; + const key = target.closest("swp-pin-key"); + if (!key) return; + const digit = key.dataset.digit; + const action = key.dataset.action; + if (digit) { + this.addDigit(digit); + } else if (action === "backspace") { + this.removeDigit(); + } else if (action === "clear") { + this.clearPin(); + } + } + handleKeyboard(e) { + if (!this.isActive) return; + e.preventDefault(); + if (e.key >= "0" && e.key <= "9") { + this.addDigit(e.key); + } else if (e.key === "Backspace") { + this.removeDigit(); + } else if (e.key === "Escape") { + this.clearPin(); + } + } +}; +__name(_LockScreenController, "LockScreenController"); +_LockScreenController.CORRECT_PIN = "1234"; +var LockScreenController = _LockScreenController; + +// wwwroot/ts/modules/cash.ts +var _CashController = class _CashController { + constructor() { + // Base values (from system - would come from server in real app) + this.startBalance = 2e3; + this.cashSales = 3540; + this.setupTabs(); + this.setupCashCalculation(); + this.setupCheckboxSelection(); + this.setupApprovalCheckbox(); + this.setupDateFilters(); + this.setupRowToggle(); + this.setupDraftRowClick(); + } + /** + * Setup tab switching functionality + */ + setupTabs() { + const tabs = document.querySelectorAll("swp-tab[data-tab]"); + tabs.forEach((tab) => { + tab.addEventListener("click", () => { + const targetTab = tab.dataset.tab; + if (targetTab) { + this.switchToTab(targetTab); + } }); + }); + } + /** + * Switch to a specific tab by name + */ + switchToTab(targetTab) { + const tabs = document.querySelectorAll("swp-tab[data-tab]"); + const contents = document.querySelectorAll("swp-tab-content[data-tab]"); + const statsBars = document.querySelectorAll("swp-cash-stats[data-for-tab]"); + tabs.forEach((t) => { + if (t.dataset.tab === targetTab) { + t.classList.add("active"); + } else { + t.classList.remove("active"); + } + }); + contents.forEach((content) => { + if (content.dataset.tab === targetTab) { + content.classList.add("active"); + } else { + content.classList.remove("active"); + } + }); + statsBars.forEach((stats) => { + if (stats.dataset.forTab === targetTab) { + stats.classList.add("active"); + } else { + stats.classList.remove("active"); + } + }); + } + /** + * Setup cash calculation with real-time updates + */ + setupCashCalculation() { + const payoutsInput = document.getElementById("payouts"); + const toBankInput = document.getElementById("toBank"); + const actualCashInput = document.getElementById("actualCash"); + if (!payoutsInput || !toBankInput || !actualCashInput) return; + const calculate = /* @__PURE__ */ __name(() => this.calculateCash(payoutsInput, toBankInput, actualCashInput), "calculate"); + payoutsInput.addEventListener("input", calculate); + toBankInput.addEventListener("input", calculate); + actualCashInput.addEventListener("input", calculate); + calculate(); + } + /** + * Calculate expected cash and difference + */ + calculateCash(payoutsInput, toBankInput, actualCashInput) { + const payouts = this.parseNumber(payoutsInput.value); + const toBank = this.parseNumber(toBankInput.value); + const actual = this.parseNumber(actualCashInput.value); + const expectedCash = this.startBalance + this.cashSales - payouts - toBank; + const expectedElement = document.getElementById("expectedCash"); + if (expectedElement) { + expectedElement.textContent = this.formatNumber(expectedCash); } - /** - * Setup approval checkbox to enable/disable approve button - */ - setupApprovalCheckbox() { - const checkbox = document.getElementById("confirmCheckbox"); - const approveBtn = document.getElementById("approveBtn"); - if (!checkbox || !approveBtn) return; - checkbox.addEventListener("change", () => { - approveBtn.disabled = !checkbox.checked; - }); + this.updateDifference(actual, expectedCash, actualCashInput.value); + } + /** + * Update difference box with color coding + */ + updateDifference(actual, expected, rawValue) { + const box = document.getElementById("differenceBox"); + const value = document.getElementById("differenceValue"); + if (!box || !value) return; + const diff = actual - expected; + box.classList.remove("positive", "negative", "neutral"); + if (actual === 0 && rawValue === "") { + value.textContent = "\u2013 kr"; + box.classList.add("neutral"); + } else if (diff > 0) { + value.textContent = "+" + this.formatNumber(diff) + " kr"; + box.classList.add("positive"); + } else if (diff < 0) { + value.textContent = this.formatNumber(diff) + " kr"; + box.classList.add("negative"); + } else { + value.textContent = "0,00 kr"; + box.classList.add("neutral"); } - /** - * Setup date filter defaults (last 30 days) - */ - setupDateFilters() { - const dateFrom = document.getElementById("dateFrom"); - const dateTo = document.getElementById("dateTo"); - if (!dateFrom || !dateTo) return; - const today = /* @__PURE__ */ new Date(); - const thirtyDaysAgo = new Date(today); - thirtyDaysAgo.setDate(today.getDate() - 30); - dateTo.value = this.formatDateISO(today); - dateFrom.value = this.formatDateISO(thirtyDaysAgo); - } - /** - * Format number as Danish currency - */ - formatNumber(num) { - return num.toLocaleString("da-DK", { - minimumFractionDigits: 2, - maximumFractionDigits: 2 - }); - } - /** - * Parse Danish number format - */ - parseNumber(str) { - if (!str) return 0; - return parseFloat(str.replace(/\./g, "").replace(",", ".")) || 0; - } - /** - * Format date as ISO string (YYYY-MM-DD) - */ - formatDateISO(date) { - return date.toISOString().split("T")[0]; - } - /** - * Setup row toggle for expandable details - */ - setupRowToggle() { - const rows = document.querySelectorAll("swp-cash-table-row[data-id]:not(.draft-row)"); - rows.forEach((row) => { - const rowId = row.getAttribute("data-id"); - if (!rowId) return; - const detail = document.querySelector(`swp-cash-row-detail[data-for="${rowId}"]`); - if (!detail) return; - row.addEventListener("click", (e) => { - if (e.target.closest('input[type="checkbox"]')) return; - const icon = row.querySelector("swp-row-toggle i"); - const isExpanded = row.classList.contains("expanded"); - document.querySelectorAll("swp-cash-table-row.expanded").forEach((r) => { - if (r !== row) { - const otherId = r.getAttribute("data-id"); - if (otherId) { - const otherDetail = document.querySelector(`swp-cash-row-detail[data-for="${otherId}"]`); - const otherIcon = r.querySelector("swp-row-toggle i"); - if (otherDetail && otherIcon) { - this.collapseRow(r, otherDetail, otherIcon); - } + } + /** + * Setup checkbox selection for table rows + */ + setupCheckboxSelection() { + const selectAll = document.getElementById("selectAll"); + const rowCheckboxes = document.querySelectorAll(".row-select"); + const exportBtn = document.getElementById("exportBtn"); + const selectionCount = document.getElementById("selectionCount"); + if (!selectAll || !exportBtn || !selectionCount) return; + const updateSelection = /* @__PURE__ */ __name(() => { + const checked = document.querySelectorAll(".row-select:checked"); + const count = checked.length; + selectionCount.textContent = count === 0 ? "0 valgt" : `${count} valgt`; + exportBtn.disabled = count === 0; + selectAll.checked = count === rowCheckboxes.length && count > 0; + selectAll.indeterminate = count > 0 && count < rowCheckboxes.length; + }, "updateSelection"); + selectAll.addEventListener("change", () => { + rowCheckboxes.forEach((cb) => cb.checked = selectAll.checked); + updateSelection(); + }); + rowCheckboxes.forEach((cb) => { + cb.addEventListener("change", updateSelection); + cb.addEventListener("click", (e) => e.stopPropagation()); + }); + } + /** + * Setup approval checkbox to enable/disable approve button + */ + setupApprovalCheckbox() { + const checkbox = document.getElementById("confirmCheckbox"); + const approveBtn = document.getElementById("approveBtn"); + if (!checkbox || !approveBtn) return; + checkbox.addEventListener("change", () => { + approveBtn.disabled = !checkbox.checked; + }); + } + /** + * Setup date filter defaults (last 30 days) + */ + setupDateFilters() { + const dateFrom = document.getElementById("dateFrom"); + const dateTo = document.getElementById("dateTo"); + if (!dateFrom || !dateTo) return; + const today = /* @__PURE__ */ new Date(); + const thirtyDaysAgo = new Date(today); + thirtyDaysAgo.setDate(today.getDate() - 30); + dateTo.value = this.formatDateISO(today); + dateFrom.value = this.formatDateISO(thirtyDaysAgo); + } + /** + * Format number as Danish currency + */ + formatNumber(num) { + return num.toLocaleString("da-DK", { + minimumFractionDigits: 2, + maximumFractionDigits: 2 + }); + } + /** + * Parse Danish number format + */ + parseNumber(str) { + if (!str) return 0; + return parseFloat(str.replace(/\./g, "").replace(",", ".")) || 0; + } + /** + * Format date as ISO string (YYYY-MM-DD) + */ + formatDateISO(date) { + return date.toISOString().split("T")[0]; + } + /** + * Setup row toggle for expandable details + */ + setupRowToggle() { + const rows = document.querySelectorAll("swp-cash-table-row[data-id]:not(.draft-row)"); + rows.forEach((row) => { + const rowId = row.getAttribute("data-id"); + if (!rowId) return; + const detail = document.querySelector(`swp-cash-row-detail[data-for="${rowId}"]`); + if (!detail) return; + row.addEventListener("click", (e) => { + if (e.target.closest('input[type="checkbox"]')) return; + const icon = row.querySelector("swp-row-toggle i"); + const isExpanded = row.classList.contains("expanded"); + document.querySelectorAll("swp-cash-table-row.expanded").forEach((r) => { + if (r !== row) { + const otherId = r.getAttribute("data-id"); + if (otherId) { + const otherDetail = document.querySelector(`swp-cash-row-detail[data-for="${otherId}"]`); + const otherIcon = r.querySelector("swp-row-toggle i"); + if (otherDetail && otherIcon) { + this.collapseRow(r, otherDetail, otherIcon); } } - }); - if (isExpanded) { - this.collapseRow(row, detail, icon); - } else { - this.expandRow(row, detail, icon); } }); + if (isExpanded) { + this.collapseRow(row, detail, icon); + } else { + this.expandRow(row, detail, icon); + } + }); + }); + } + /** + * Expand a row with animation + */ + expandRow(row, detail, icon) { + row.classList.add("expanded"); + detail.classList.add("expanded"); + icon?.animate([ + { transform: "rotate(0deg)" }, + { transform: "rotate(90deg)" } + ], { + duration: 200, + easing: "ease-out", + fill: "forwards" + }); + const content = detail.querySelector("swp-row-detail-content"); + if (content) { + const height = content.offsetHeight; + detail.animate([ + { height: "0px", opacity: 0 }, + { height: `${height}px`, opacity: 1 } + ], { + duration: 250, + easing: "ease-out", + fill: "forwards" }); } - /** - * Expand a row with animation - */ - expandRow(row, detail, icon) { - row.classList.add("expanded"); - detail.classList.add("expanded"); - icon?.animate([ - { transform: "rotate(0deg)" }, - { transform: "rotate(90deg)" } + } + /** + * Collapse a row with animation + */ + collapseRow(row, detail, icon) { + icon?.animate([ + { transform: "rotate(90deg)" }, + { transform: "rotate(0deg)" } + ], { + duration: 200, + easing: "ease-out", + fill: "forwards" + }); + const content = detail.querySelector("swp-row-detail-content"); + if (content) { + const height = content.offsetHeight; + const animation = detail.animate([ + { height: `${height}px`, opacity: 1 }, + { height: "0px", opacity: 0 } ], { duration: 200, easing: "ease-out", fill: "forwards" }); - const content = detail.querySelector("swp-row-detail-content"); - if (content) { - const height = content.offsetHeight; - detail.animate([ - { height: "0px", opacity: 0 }, - { height: `${height}px`, opacity: 1 } - ], { - duration: 250, - easing: "ease-out", - fill: "forwards" - }); - } - } - /** - * Collapse a row with animation - */ - collapseRow(row, detail, icon) { - icon?.animate([ - { transform: "rotate(90deg)" }, - { transform: "rotate(0deg)" } - ], { - duration: 200, - easing: "ease-out", - fill: "forwards" - }); - const content = detail.querySelector("swp-row-detail-content"); - if (content) { - const height = content.offsetHeight; - const animation = detail.animate([ - { height: `${height}px`, opacity: 1 }, - { height: "0px", opacity: 0 } - ], { - duration: 200, - easing: "ease-out", - fill: "forwards" - }); - animation.onfinish = () => { - row.classList.remove("expanded"); - detail.classList.remove("expanded"); - }; - } else { + animation.onfinish = () => { row.classList.remove("expanded"); detail.classList.remove("expanded"); - } + }; + } else { + row.classList.remove("expanded"); + detail.classList.remove("expanded"); } - /** - * Setup draft row click to navigate to reconciliation tab - */ - setupDraftRowClick() { - const draftRow = document.querySelector("swp-cash-table-row.draft-row"); - if (!draftRow) return; - draftRow.style.cursor = "pointer"; - draftRow.addEventListener("click", (e) => { - if (e.target.closest('input[type="checkbox"]')) return; - this.switchToTab("afstemning"); - }); - } - }; + } + /** + * Setup draft row click to navigate to reconciliation tab + */ + setupDraftRowClick() { + const draftRow = document.querySelector("swp-cash-table-row.draft-row"); + if (!draftRow) return; + draftRow.style.cursor = "pointer"; + draftRow.addEventListener("click", (e) => { + if (e.target.closest('input[type="checkbox"]')) return; + this.switchToTab("afstemning"); + }); + } +}; +__name(_CashController, "CashController"); +var CashController = _CashController; - // wwwroot/ts/modules/employees.ts - var EmployeesController = class { - constructor() { - this.ratesSync = null; - this.listView = null; - this.detailView = null; - this.listView = document.getElementById("employees-list-view"); - this.detailView = document.getElementById("employee-detail-view"); - if (!this.listView) return; - this.setupListTabs(); - this.setupDetailTabs(); - this.setupChevronNavigation(); - this.setupBackNavigation(); - this.setupHistoryNavigation(); - this.restoreStateFromUrl(); - this.ratesSync = new RatesSyncController(); - } - /** - * Setup popstate listener for browser back/forward - */ - setupHistoryNavigation() { - window.addEventListener("popstate", (e) => { - if (e.state?.employeeKey) { - this.showDetailViewInternal(e.state.employeeKey); - } else { - this.showListViewInternal(); - } - }); - } - /** - * Restore view state from URL on page load - */ - restoreStateFromUrl() { - const hash = window.location.hash; - if (hash.startsWith("#employee-")) { - const employeeKey = hash.substring(1); - this.showDetailViewInternal(employeeKey); +// wwwroot/ts/modules/employees.ts +var _EmployeesController = class _EmployeesController { + constructor() { + this.ratesSync = null; + this.listView = null; + this.detailView = null; + this.listView = document.getElementById("employees-list-view"); + this.detailView = document.getElementById("employee-detail-view"); + if (!this.listView) return; + this.setupListTabs(); + this.setupDetailTabs(); + this.setupChevronNavigation(); + this.setupBackNavigation(); + this.setupHistoryNavigation(); + this.restoreStateFromUrl(); + this.ratesSync = new RatesSyncController(); + } + /** + * Setup popstate listener for browser back/forward + */ + setupHistoryNavigation() { + window.addEventListener("popstate", (e) => { + if (e.state?.employeeKey) { + this.showDetailViewInternal(e.state.employeeKey); + } else { + this.showListViewInternal(); } - } - /** - * Setup tab switching for the list view - */ - setupListTabs() { - if (!this.listView) return; - const tabs = this.listView.querySelectorAll("swp-tab-bar > swp-tab[data-tab]"); - tabs.forEach((tab) => { - tab.addEventListener("click", () => { - const targetTab = tab.dataset.tab; - if (targetTab) { - this.switchTab(this.listView, targetTab); - } - }); - }); - } - /** - * Setup tab switching for the detail view - */ - setupDetailTabs() { - if (!this.detailView) return; - const tabs = this.detailView.querySelectorAll("swp-tab-bar > swp-tab[data-tab]"); - tabs.forEach((tab) => { - tab.addEventListener("click", () => { - const targetTab = tab.dataset.tab; - if (targetTab) { - this.switchTab(this.detailView, targetTab); - } - }); - }); - } - /** - * Switch to a specific tab within a container - */ - switchTab(container, targetTab) { - const tabs = container.querySelectorAll("swp-tab-bar > swp-tab[data-tab]"); - const contents = container.querySelectorAll("swp-tab-content[data-tab]"); - tabs.forEach((t) => { - t.classList.toggle("active", t.dataset.tab === targetTab); - }); - contents.forEach((content) => { - content.classList.toggle("active", content.dataset.tab === targetTab); - }); - } - /** - * Setup row click to show detail view - * Ignores clicks on action buttons - */ - setupChevronNavigation() { - document.addEventListener("click", (e) => { - const target = e.target; - if (target.closest("swp-icon-btn") || target.closest("swp-table-actions")) { - return; - } - const row = target.closest("swp-employee-row[data-employee-detail]"); - if (row) { - const employeeKey = row.dataset.employeeDetail; - if (employeeKey) { - this.showDetailView(employeeKey); - } - } - }); - } - /** - * Setup back button to return to list view - */ - setupBackNavigation() { - document.addEventListener("click", (e) => { - const target = e.target; - const backLink = target.closest("[data-employee-back]"); - if (backLink) { - this.showListView(); - } - }); - } - /** - * Show the detail view and hide list view (with history push) - */ - showDetailView(employeeKey) { - history.pushState( - { employeeKey }, - "", - `#${employeeKey}` - ); + }); + } + /** + * Restore view state from URL on page load + */ + restoreStateFromUrl() { + const hash = window.location.hash; + if (hash.startsWith("#employee-")) { + const employeeKey = hash.substring(1); this.showDetailViewInternal(employeeKey); } - /** - * Show detail view without modifying history (for popstate) - */ - showDetailViewInternal(employeeKey) { - if (this.listView && this.detailView) { - this.listView.style.display = "none"; - this.detailView.style.display = "block"; - this.detailView.dataset.employee = employeeKey; - this.switchTab(this.detailView, "general"); - } - } - /** - * Show the list view and hide detail view (with history push) - */ - showListView() { - history.pushState( - {}, - "", - window.location.pathname - ); - this.showListViewInternal(); - } - /** - * Show list view without modifying history (for popstate) - */ - showListViewInternal() { - if (this.listView && this.detailView) { - this.detailView.style.display = "none"; - this.listView.style.display = "block"; - } - } - }; - var RatesSyncController = class { - constructor() { - this.drawer = null; - this.drawer = document.getElementById("rates-drawer"); - if (!this.drawer) return; - this.setupCheckboxListeners(); - this.setupInputListeners(); - } - /** - * Extract rate key from checkbox ID (e.g., "rate-normal-enabled" → "normal") - */ - extractRateKey(checkboxId) { - const match = checkboxId.match(/^rate-(.+)-enabled$/); - return match ? match[1] : null; - } - /** - * Setup checkbox change listeners in drawer - */ - setupCheckboxListeners() { - if (!this.drawer) return; - this.drawer.addEventListener("change", (e) => { - const target = e.target; - if (target.type !== "checkbox" || !target.id) return; - const rateKey = this.extractRateKey(target.id); - if (!rateKey) return; - const isChecked = target.checked; - const row = target.closest("swp-data-row"); - if (!row) return; - const label = row.querySelector("swp-data-label"); - const input = row.querySelector("swp-data-input"); - if (label) label.classList.toggle("disabled", !isChecked); - if (input) input.classList.toggle("disabled", !isChecked); - this.toggleCardRow(rateKey, isChecked); - if (isChecked) { - const textInput = document.getElementById(`rate-${rateKey}`); - if (textInput) { - this.syncValueToCard(rateKey, textInput.value); - } + } + /** + * Setup tab switching for the list view + */ + setupListTabs() { + if (!this.listView) return; + const tabs = this.listView.querySelectorAll("swp-tab-bar > swp-tab[data-tab]"); + tabs.forEach((tab) => { + tab.addEventListener("click", () => { + const targetTab = tab.dataset.tab; + if (targetTab) { + this.switchTab(this.listView, targetTab); } }); - } - /** - * Setup input change listeners in drawer - */ - setupInputListeners() { - if (!this.drawer) return; - this.drawer.addEventListener("input", (e) => { - const target = e.target; - if (target.type !== "text" || !target.id) return; - const match = target.id.match(/^rate-(.+)$/); - if (!match) return; - const rateKey = match[1]; - if (rateKey.endsWith("-enabled")) return; - this.syncValueToCard(rateKey, target.value); + }); + } + /** + * Setup tab switching for the detail view + */ + setupDetailTabs() { + if (!this.detailView) return; + const tabs = this.detailView.querySelectorAll("swp-tab-bar > swp-tab[data-tab]"); + tabs.forEach((tab) => { + tab.addEventListener("click", () => { + const targetTab = tab.dataset.tab; + if (targetTab) { + this.switchTab(this.detailView, targetTab); + } }); - } - /** - * Toggle card row visibility by ID - */ - toggleCardRow(rateKey, visible) { - const cardRow = document.getElementById(`card-${rateKey}`); - if (cardRow) { - cardRow.style.display = visible ? "" : "none"; + }); + } + /** + * Switch to a specific tab within a container + */ + switchTab(container, targetTab) { + const tabs = container.querySelectorAll("swp-tab-bar > swp-tab[data-tab]"); + const contents = container.querySelectorAll("swp-tab-content[data-tab]"); + tabs.forEach((t) => { + t.classList.toggle("active", t.dataset.tab === targetTab); + }); + contents.forEach((content) => { + content.classList.toggle("active", content.dataset.tab === targetTab); + }); + } + /** + * Setup row click to show detail view + * Ignores clicks on action buttons + */ + setupChevronNavigation() { + document.addEventListener("click", (e) => { + const target = e.target; + if (target.closest("swp-icon-btn") || target.closest("swp-table-actions")) { + return; } + const row = target.closest("swp-data-table-row[data-employee-detail]"); + if (row) { + const employeeKey = row.dataset.employeeDetail; + if (employeeKey) { + this.showDetailView(employeeKey); + } + } + }); + } + /** + * Setup back button to return to list view + */ + setupBackNavigation() { + document.addEventListener("click", (e) => { + const target = e.target; + const backLink = target.closest("[data-employee-back]"); + if (backLink) { + this.showListView(); + } + }); + } + /** + * Show the detail view and hide list view (with history push) + */ + showDetailView(employeeKey) { + history.pushState( + { employeeKey }, + "", + `#${employeeKey}` + ); + this.showDetailViewInternal(employeeKey); + } + /** + * Show detail view without modifying history (for popstate) + */ + showDetailViewInternal(employeeKey) { + if (this.listView && this.detailView) { + this.listView.style.display = "none"; + this.detailView.style.display = "block"; + this.detailView.dataset.employee = employeeKey; + this.switchTab(this.detailView, "general"); } - /** - * Format number with 2 decimals using Danish locale (comma as decimal separator) - */ - formatNumber(value) { - const normalized = value.replace(",", "."); - const num = parseFloat(normalized); - if (isNaN(num)) return value; - return num.toFixed(2).replace(".", ","); + } + /** + * Show the list view and hide detail view (with history push) + */ + showListView() { + history.pushState( + {}, + "", + window.location.pathname + ); + this.showListViewInternal(); + } + /** + * Show list view without modifying history (for popstate) + */ + showListViewInternal() { + if (this.listView && this.detailView) { + this.detailView.style.display = "none"; + this.listView.style.display = "block"; } - /** - * Sync value from drawer to card by ID - */ - syncValueToCard(rateKey, value) { - const cardInput = document.getElementById(`value-${rateKey}`); - if (!cardInput) return; - const textInput = document.getElementById(`rate-${rateKey}`); - const inputContainer = textInput?.closest("swp-data-input"); - const unit = inputContainer?.textContent?.trim().replace(value, "").trim() || "kr"; - const formattedValue = this.formatNumber(value); - cardInput.value = `${formattedValue} ${unit}`; + } +}; +__name(_EmployeesController, "EmployeesController"); +var EmployeesController = _EmployeesController; +var _RatesSyncController = class _RatesSyncController { + constructor() { + this.drawer = null; + this.drawer = document.getElementById("rates-drawer"); + if (!this.drawer) return; + this.setupCheckboxListeners(); + this.setupInputListeners(); + } + /** + * Extract rate key from checkbox ID (e.g., "rate-normal-enabled" → "normal") + */ + extractRateKey(checkboxId) { + const match = checkboxId.match(/^rate-(.+)-enabled$/); + return match ? match[1] : null; + } + /** + * Setup checkbox change listeners in drawer + */ + setupCheckboxListeners() { + if (!this.drawer) return; + this.drawer.addEventListener("change", (e) => { + const target = e.target; + if (target.type !== "checkbox" || !target.id) return; + const rateKey = this.extractRateKey(target.id); + if (!rateKey) return; + const isChecked = target.checked; + const row = target.closest("swp-data-row"); + if (!row) return; + const label = row.querySelector("swp-data-label"); + const input = row.querySelector("swp-data-input"); + if (label) label.classList.toggle("disabled", !isChecked); + if (input) input.classList.toggle("disabled", !isChecked); + this.toggleCardRow(rateKey, isChecked); + if (isChecked) { + const textInput = document.getElementById(`rate-${rateKey}`); + if (textInput) { + this.syncValueToCard(rateKey, textInput.value); + } + } + }); + } + /** + * Setup input change listeners in drawer + */ + setupInputListeners() { + if (!this.drawer) return; + this.drawer.addEventListener("input", (e) => { + const target = e.target; + if (target.type !== "text" || !target.id) return; + const match = target.id.match(/^rate-(.+)$/); + if (!match) return; + const rateKey = match[1]; + if (rateKey.endsWith("-enabled")) return; + this.syncValueToCard(rateKey, target.value); + }); + } + /** + * Toggle card row visibility by ID + */ + toggleCardRow(rateKey, visible) { + const cardRow = document.getElementById(`card-${rateKey}`); + if (cardRow) { + cardRow.style.display = visible ? "" : "none"; } - }; + } + /** + * Format number with 2 decimals using Danish locale (comma as decimal separator) + */ + formatNumber(value) { + const normalized = value.replace(",", "."); + const num = parseFloat(normalized); + if (isNaN(num)) return value; + return num.toFixed(2).replace(".", ","); + } + /** + * Sync value from drawer to card by ID + */ + syncValueToCard(rateKey, value) { + const cardInput = document.getElementById(`value-${rateKey}`); + if (!cardInput) return; + const textInput = document.getElementById(`rate-${rateKey}`); + const inputContainer = textInput?.closest("swp-data-input"); + const unit = inputContainer?.textContent?.trim().replace(value, "").trim() || "kr"; + const formattedValue = this.formatNumber(value); + cardInput.value = `${formattedValue} ${unit}`; + } +}; +__name(_RatesSyncController, "RatesSyncController"); +var RatesSyncController = _RatesSyncController; - // wwwroot/ts/app.ts - var App = class { - constructor() { - this.sidebar = new SidebarController(); - this.drawers = new DrawerController(); - this.theme = new ThemeController(); - this.search = new SearchController(); - this.lockScreen = new LockScreenController(this.drawers); - this.cash = new CashController(); - this.employees = new EmployeesController(); - } - }; - var app; - function init() { - app = new App(); - if (typeof window !== "undefined") { - window.app = app; - } +// wwwroot/ts/app.ts +var _App = class _App { + constructor() { + this.sidebar = new SidebarController(); + this.drawers = new DrawerController(); + this.theme = new ThemeController(); + this.search = new SearchController(); + this.lockScreen = new LockScreenController(this.drawers); + this.cash = new CashController(); + this.employees = new EmployeesController(); } - if (document.readyState === "loading") { - document.addEventListener("DOMContentLoaded", init); - } else { - init(); +}; +__name(_App, "App"); +var App = _App; +var app; +function init() { + app = new App(); + if (typeof window !== "undefined") { + window.app = app; } - var app_default = App; -})(); -//# sourceMappingURL=app.js.map +} +__name(init, "init"); +if (document.readyState === "loading") { + document.addEventListener("DOMContentLoaded", init); +} else { + init(); +} +var app_default = App; +export { + App, + app, + app_default as default +}; +//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vdHMvbW9kdWxlcy9zaWRlYmFyLnRzIiwgIi4uL3RzL21vZHVsZXMvZHJhd2Vycy50cyIsICIuLi90cy9tb2R1bGVzL3RoZW1lLnRzIiwgIi4uL3RzL21vZHVsZXMvc2VhcmNoLnRzIiwgIi4uL3RzL21vZHVsZXMvbG9ja3NjcmVlbi50cyIsICIuLi90cy9tb2R1bGVzL2Nhc2gudHMiLCAiLi4vdHMvbW9kdWxlcy9lbXBsb3llZXMudHMiLCAiLi4vdHMvYXBwLnRzIl0sCiAgInNvdXJjZXNDb250ZW50IjogWyIvKipcbiAqIFNpZGViYXIgQ29udHJvbGxlclxuICpcbiAqIEhhbmRsZXMgc2lkZWJhciBjb2xsYXBzZS9leHBhbmQgYW5kIHRvb2x0aXAgZnVuY3Rpb25hbGl0eVxuICovXG5cbmV4cG9ydCBjbGFzcyBTaWRlYmFyQ29udHJvbGxlciB7XG4gIHByaXZhdGUgbWVudVRvZ2dsZTogSFRNTEVsZW1lbnQgfCBudWxsID0gbnVsbDtcbiAgcHJpdmF0ZSBhcHBMYXlvdXQ6IEhUTUxFbGVtZW50IHwgbnVsbCA9IG51bGw7XG4gIHByaXZhdGUgbWVudVRvb2x0aXA6IEhUTUxFbGVtZW50IHwgbnVsbCA9IG51bGw7XG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgdGhpcy5tZW51VG9nZ2xlID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ21lbnVUb2dnbGUnKTtcbiAgICB0aGlzLmFwcExheW91dCA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJ3N3cC1hcHAtbGF5b3V0Jyk7XG4gICAgdGhpcy5tZW51VG9vbHRpcCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdtZW51VG9vbHRpcCcpO1xuXG4gICAgdGhpcy5zZXR1cExpc3RlbmVycygpO1xuICAgIHRoaXMuc2V0dXBUb29sdGlwcygpO1xuICAgIHRoaXMucmVzdG9yZVN0YXRlKCk7XG4gIH1cblxuICAvKipcbiAgICogQ2hlY2sgaWYgc2lkZWJhciBpcyBjb2xsYXBzZWRcbiAgICovXG4gIGdldCBpc0NvbGxhcHNlZCgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5hcHBMYXlvdXQ/LmNsYXNzTGlzdC5jb250YWlucygnbWVudS1jb2xsYXBzZWQnKSA/PyBmYWxzZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBUb2dnbGUgc2lkZWJhciBjb2xsYXBzZWQgc3RhdGVcbiAgICovXG4gIHRvZ2dsZSgpOiB2b2lkIHtcbiAgICBpZiAoIXRoaXMuYXBwTGF5b3V0KSByZXR1cm47XG5cbiAgICB0aGlzLmFwcExheW91dC5jbGFzc0xpc3QudG9nZ2xlKCdtZW51LWNvbGxhcHNlZCcpO1xuICAgIGxvY2FsU3RvcmFnZS5zZXRJdGVtKCdzaWRlYmFyLWNvbGxhcHNlZCcsIFN0cmluZyh0aGlzLmlzQ29sbGFwc2VkKSk7XG4gIH1cblxuICAvKipcbiAgICogQ29sbGFwc2UgdGhlIHNpZGViYXJcbiAgICovXG4gIGNvbGxhcHNlKCk6IHZvaWQge1xuICAgIHRoaXMuYXBwTGF5b3V0Py5jbGFzc0xpc3QuYWRkKCdtZW51LWNvbGxhcHNlZCcpO1xuICAgIGxvY2FsU3RvcmFnZS5zZXRJdGVtKCdzaWRlYmFyLWNvbGxhcHNlZCcsICd0cnVlJyk7XG4gIH1cblxuICAvKipcbiAgICogRXhwYW5kIHRoZSBzaWRlYmFyXG4gICAqL1xuICBleHBhbmQoKTogdm9pZCB7XG4gICAgdGhpcy5hcHBMYXlvdXQ/LmNsYXNzTGlzdC5yZW1vdmUoJ21lbnUtY29sbGFwc2VkJyk7XG4gICAgbG9jYWxTdG9yYWdlLnNldEl0ZW0oJ3NpZGViYXItY29sbGFwc2VkJywgJ2ZhbHNlJyk7XG4gIH1cblxuICBwcml2YXRlIHNldHVwTGlzdGVuZXJzKCk6IHZvaWQge1xuICAgIHRoaXMubWVudVRvZ2dsZT8uYWRkRXZlbnRMaXN0ZW5lcignY2xpY2snLCAoKSA9PiB0aGlzLnRvZ2dsZSgpKTtcbiAgfVxuXG4gIHByaXZhdGUgc2V0dXBUb29sdGlwcygpOiB2b2lkIHtcbiAgICBpZiAoIXRoaXMubWVudVRvb2x0aXApIHJldHVybjtcblxuICAgIGNvbnN0IG1lbnVJdGVtcyA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3JBbGw8SFRNTEVsZW1lbnQ+KCdzd3Atc2lkZS1tZW51LWl0ZW1bZGF0YS10b29sdGlwXScpO1xuXG4gICAgbWVudUl0ZW1zLmZvckVhY2goaXRlbSA9PiB7XG4gICAgICBpdGVtLmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNlZW50ZXInLCAoKSA9PiB0aGlzLnNob3dUb29sdGlwKGl0ZW0pKTtcbiAgICAgIGl0ZW0uYWRkRXZlbnRMaXN0ZW5lcignbW91c2VsZWF2ZScsICgpID0+IHRoaXMuaGlkZVRvb2x0aXAoKSk7XG4gICAgfSk7XG4gIH1cblxuICBwcml2YXRlIHNob3dUb29sdGlwKGl0ZW06IEhUTUxFbGVtZW50KTogdm9pZCB7XG4gICAgaWYgKCF0aGlzLmlzQ29sbGFwc2VkIHx8ICF0aGlzLm1lbnVUb29sdGlwKSByZXR1cm47XG5cbiAgICBjb25zdCByZWN0ID0gaXRlbS5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICBjb25zdCB0b29sdGlwVGV4dCA9IGl0ZW0uZGF0YXNldC50b29sdGlwO1xuXG4gICAgaWYgKCF0b29sdGlwVGV4dCkgcmV0dXJuO1xuXG4gICAgdGhpcy5tZW51VG9vbHRpcC50ZXh0Q29udGVudCA9IHRvb2x0aXBUZXh0O1xuICAgIHRoaXMubWVudVRvb2x0aXAuc3R5bGUubGVmdCA9IGAke3JlY3QucmlnaHQgKyA4fXB4YDtcbiAgICB0aGlzLm1lbnVUb29sdGlwLnN0eWxlLnRvcCA9IGAke3JlY3QudG9wICsgcmVjdC5oZWlnaHQgLyAyfXB4YDtcbiAgICB0aGlzLm1lbnVUb29sdGlwLnN0eWxlLnRyYW5zZm9ybSA9ICd0cmFuc2xhdGVZKC01MCUpJztcbiAgICB0aGlzLm1lbnVUb29sdGlwLnNob3dQb3BvdmVyKCk7XG4gIH1cblxuICBwcml2YXRlIGhpZGVUb29sdGlwKCk6IHZvaWQge1xuICAgIHRoaXMubWVudVRvb2x0aXA/LmhpZGVQb3BvdmVyKCk7XG4gIH1cblxuICBwcml2YXRlIHJlc3RvcmVTdGF0ZSgpOiB2b2lkIHtcbiAgICBpZiAoIXRoaXMuYXBwTGF5b3V0KSByZXR1cm47XG5cbiAgICBpZiAobG9jYWxTdG9yYWdlLmdldEl0ZW0oJ3NpZGViYXItY29sbGFwc2VkJykgPT09ICd0cnVlJykge1xuICAgICAgdGhpcy5hcHBMYXlvdXQuY2xhc3NMaXN0LmFkZCgnbWVudS1jb2xsYXBzZWQnKTtcbiAgICB9XG4gIH1cbn1cbiIsICIvKipcbiAqIERyYXdlciBDb250cm9sbGVyXG4gKlxuICogSGFuZGxlcyBhbGwgZHJhd2VyIGZ1bmN0aW9uYWxpdHkgaW5jbHVkaW5nIHByb2ZpbGUsIG5vdGlmaWNhdGlvbnMsIGFuZCB0b2RvIGRyYXdlcnNcbiAqL1xuXG5leHBvcnQgdHlwZSBEcmF3ZXJOYW1lID0gJ3Byb2ZpbGUnIHwgJ25vdGlmaWNhdGlvbicgfCAndG9kbycgfCAnbmV3VG9kbyc7XG5cbmV4cG9ydCBjbGFzcyBEcmF3ZXJDb250cm9sbGVyIHtcbiAgcHJpdmF0ZSBwcm9maWxlRHJhd2VyOiBIVE1MRWxlbWVudCB8IG51bGwgPSBudWxsO1xuICBwcml2YXRlIG5vdGlmaWNhdGlvbkRyYXdlcjogSFRNTEVsZW1lbnQgfCBudWxsID0gbnVsbDtcbiAgcHJpdmF0ZSB0b2RvRHJhd2VyOiBIVE1MRWxlbWVudCB8IG51bGwgPSBudWxsO1xuICBwcml2YXRlIG5ld1RvZG9EcmF3ZXI6IEhUTUxFbGVtZW50IHwgbnVsbCA9IG51bGw7XG4gIHByaXZhdGUgb3ZlcmxheTogSFRNTEVsZW1lbnQgfCBudWxsID0gbnVsbDtcbiAgcHJpdmF0ZSBhY3RpdmVEcmF3ZXI6IERyYXdlck5hbWUgfCBudWxsID0gbnVsbDtcbiAgcHJpdmF0ZSBhY3RpdmVHZW5lcmljRHJhd2VyOiBIVE1MRWxlbWVudCB8IG51bGwgPSBudWxsO1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHRoaXMucHJvZmlsZURyYXdlciA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdwcm9maWxlRHJhd2VyJyk7XG4gICAgdGhpcy5ub3RpZmljYXRpb25EcmF3ZXIgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnbm90aWZpY2F0aW9uRHJhd2VyJyk7XG4gICAgdGhpcy50b2RvRHJhd2VyID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ3RvZG9EcmF3ZXInKTtcbiAgICB0aGlzLm5ld1RvZG9EcmF3ZXIgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnbmV3VG9kb0RyYXdlcicpO1xuICAgIHRoaXMub3ZlcmxheSA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdkcmF3ZXJPdmVybGF5Jyk7XG5cbiAgICB0aGlzLnNldHVwTGlzdGVuZXJzKCk7XG4gICAgdGhpcy5zZXR1cEdlbmVyaWNEcmF3ZXJzKCk7XG4gIH1cblxuICAvKipcbiAgICogR2V0IGN1cnJlbnRseSBhY3RpdmUgZHJhd2VyIG5hbWVcbiAgICovXG4gIGdldCBhY3RpdmUoKTogRHJhd2VyTmFtZSB8IG51bGwge1xuICAgIHJldHVybiB0aGlzLmFjdGl2ZURyYXdlcjtcbiAgfVxuXG4gIC8qKlxuICAgKiBPcGVuIGEgZHJhd2VyIGJ5IG5hbWVcbiAgICovXG4gIG9wZW4obmFtZTogRHJhd2VyTmFtZSk6IHZvaWQge1xuICAgIHRoaXMuY2xvc2VBbGwoKTtcblxuICAgIGNvbnN0IGRyYXdlciA9IHRoaXMuZ2V0RHJhd2VyKG5hbWUpO1xuICAgIGlmIChkcmF3ZXIgJiYgdGhpcy5vdmVybGF5KSB7XG4gICAgICBkcmF3ZXIuY2xhc3NMaXN0LmFkZCgnYWN0aXZlJyk7XG4gICAgICB0aGlzLm92ZXJsYXkuY2xhc3NMaXN0LmFkZCgnYWN0aXZlJyk7XG4gICAgICBkb2N1bWVudC5ib2R5LnN0eWxlLm92ZXJmbG93ID0gJ2hpZGRlbic7XG4gICAgICB0aGlzLmFjdGl2ZURyYXdlciA9IG5hbWU7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIENsb3NlIGEgc3BlY2lmaWMgZHJhd2VyXG4gICAqL1xuICBjbG9zZShuYW1lOiBEcmF3ZXJOYW1lKTogdm9pZCB7XG4gICAgY29uc3QgZHJhd2VyID0gdGhpcy5nZXREcmF3ZXIobmFtZSk7XG4gICAgZHJhd2VyPy5jbGFzc0xpc3QucmVtb3ZlKCdhY3RpdmUnKTtcblxuICAgIC8vIE9ubHkgaGlkZSBvdmVybGF5IGlmIG5vIGRyYXdlcnMgYXJlIGFjdGl2ZVxuICAgIGlmICh0aGlzLm92ZXJsYXkgJiYgIWRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJy5hY3RpdmVbY2xhc3MqPVwiZHJhd2VyXCJdJykpIHtcbiAgICAgIHRoaXMub3ZlcmxheS5jbGFzc0xpc3QucmVtb3ZlKCdhY3RpdmUnKTtcbiAgICAgIGRvY3VtZW50LmJvZHkuc3R5bGUub3ZlcmZsb3cgPSAnJztcbiAgICB9XG5cbiAgICBpZiAodGhpcy5hY3RpdmVEcmF3ZXIgPT09IG5hbWUpIHtcbiAgICAgIHRoaXMuYWN0aXZlRHJhd2VyID0gbnVsbDtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQ2xvc2UgYWxsIGRyYXdlcnNcbiAgICovXG4gIGNsb3NlQWxsKCk6IHZvaWQge1xuICAgIFt0aGlzLnByb2ZpbGVEcmF3ZXIsIHRoaXMubm90aWZpY2F0aW9uRHJhd2VyLCB0aGlzLnRvZG9EcmF3ZXIsIHRoaXMubmV3VG9kb0RyYXdlcl1cbiAgICAgIC5mb3JFYWNoKGRyYXdlciA9PiBkcmF3ZXI/LmNsYXNzTGlzdC5yZW1vdmUoJ2FjdGl2ZScpKTtcblxuICAgIC8vIENsb3NlIGFueSBnZW5lcmljIGRyYXdlcnNcbiAgICB0aGlzLmNsb3NlR2VuZXJpY0RyYXdlcigpO1xuXG4gICAgdGhpcy5vdmVybGF5Py5jbGFzc0xpc3QucmVtb3ZlKCdhY3RpdmUnKTtcbiAgICBkb2N1bWVudC5ib2R5LnN0eWxlLm92ZXJmbG93ID0gJyc7XG4gICAgdGhpcy5hY3RpdmVEcmF3ZXIgPSBudWxsO1xuICB9XG5cbiAgLyoqXG4gICAqIE9wZW4gYSBnZW5lcmljIGRyYXdlciBieSBJRFxuICAgKi9cbiAgb3BlbkdlbmVyaWNEcmF3ZXIoZHJhd2VySWQ6IHN0cmluZyk6IHZvaWQge1xuICAgIHRoaXMuY2xvc2VBbGwoKTtcblxuICAgIGNvbnN0IGRyYXdlciA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKGRyYXdlcklkKTtcbiAgICBpZiAoZHJhd2VyICYmIHRoaXMub3ZlcmxheSkge1xuICAgICAgZHJhd2VyLmNsYXNzTGlzdC5hZGQoJ29wZW4nKTtcbiAgICAgIHRoaXMub3ZlcmxheS5jbGFzc0xpc3QuYWRkKCdhY3RpdmUnKTtcbiAgICAgIGRvY3VtZW50LmJvZHkuc3R5bGUub3ZlcmZsb3cgPSAnaGlkZGVuJztcbiAgICAgIHRoaXMuYWN0aXZlR2VuZXJpY0RyYXdlciA9IGRyYXdlcjtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQ2xvc2UgdGhlIGN1cnJlbnRseSBvcGVuIGdlbmVyaWMgZHJhd2VyXG4gICAqL1xuICBjbG9zZUdlbmVyaWNEcmF3ZXIoKTogdm9pZCB7XG4gICAgdGhpcy5hY3RpdmVHZW5lcmljRHJhd2VyPy5jbGFzc0xpc3QucmVtb3ZlKCdvcGVuJyk7XG4gICAgdGhpcy5hY3RpdmVHZW5lcmljRHJhd2VyID0gbnVsbDtcbiAgfVxuXG4gIC8qKlxuICAgKiBPcGVuIHByb2ZpbGUgZHJhd2VyXG4gICAqL1xuICBvcGVuUHJvZmlsZSgpOiB2b2lkIHtcbiAgICB0aGlzLm9wZW4oJ3Byb2ZpbGUnKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBPcGVuIG5vdGlmaWNhdGlvbiBkcmF3ZXJcbiAgICovXG4gIG9wZW5Ob3RpZmljYXRpb24oKTogdm9pZCB7XG4gICAgdGhpcy5vcGVuKCdub3RpZmljYXRpb24nKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBPcGVuIHRvZG8gZHJhd2VyIChzbGlkZXMgb24gdG9wIG9mIHByb2ZpbGUpXG4gICAqL1xuICBvcGVuVG9kbygpOiB2b2lkIHtcbiAgICB0aGlzLnRvZG9EcmF3ZXI/LmNsYXNzTGlzdC5hZGQoJ2FjdGl2ZScpO1xuICB9XG5cbiAgLyoqXG4gICAqIENsb3NlIHRvZG8gZHJhd2VyXG4gICAqL1xuICBjbG9zZVRvZG8oKTogdm9pZCB7XG4gICAgdGhpcy50b2RvRHJhd2VyPy5jbGFzc0xpc3QucmVtb3ZlKCdhY3RpdmUnKTtcbiAgICB0aGlzLmNsb3NlTmV3VG9kbygpO1xuICB9XG5cbiAgLyoqXG4gICAqIE9wZW4gbmV3IHRvZG8gZHJhd2VyXG4gICAqL1xuICBvcGVuTmV3VG9kbygpOiB2b2lkIHtcbiAgICB0aGlzLm5ld1RvZG9EcmF3ZXI/LmNsYXNzTGlzdC5hZGQoJ2FjdGl2ZScpO1xuICB9XG5cbiAgLyoqXG4gICAqIENsb3NlIG5ldyB0b2RvIGRyYXdlclxuICAgKi9cbiAgY2xvc2VOZXdUb2RvKCk6IHZvaWQge1xuICAgIHRoaXMubmV3VG9kb0RyYXdlcj8uY2xhc3NMaXN0LnJlbW92ZSgnYWN0aXZlJyk7XG4gIH1cblxuICAvKipcbiAgICogTWFyayBhbGwgbm90aWZpY2F0aW9ucyBhcyByZWFkXG4gICAqL1xuICBtYXJrQWxsTm90aWZpY2F0aW9uc1JlYWQoKTogdm9pZCB7XG4gICAgaWYgKCF0aGlzLm5vdGlmaWNhdGlvbkRyYXdlcikgcmV0dXJuO1xuXG4gICAgY29uc3QgdW5yZWFkSXRlbXMgPSB0aGlzLm5vdGlmaWNhdGlvbkRyYXdlci5xdWVyeVNlbGVjdG9yQWxsPEhUTUxFbGVtZW50PihcbiAgICAgICdzd3Atbm90aWZpY2F0aW9uLWl0ZW1bZGF0YS11bnJlYWQ9XCJ0cnVlXCJdJ1xuICAgICk7XG4gICAgdW5yZWFkSXRlbXMuZm9yRWFjaChpdGVtID0+IGl0ZW0ucmVtb3ZlQXR0cmlidXRlKCdkYXRhLXVucmVhZCcpKTtcblxuICAgIGNvbnN0IGJhZGdlID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcjxIVE1MRWxlbWVudD4oJ3N3cC1ub3RpZmljYXRpb24tYmFkZ2UnKTtcbiAgICBpZiAoYmFkZ2UpIHtcbiAgICAgIGJhZGdlLnN0eWxlLmRpc3BsYXkgPSAnbm9uZSc7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBnZXREcmF3ZXIobmFtZTogRHJhd2VyTmFtZSk6IEhUTUxFbGVtZW50IHwgbnVsbCB7XG4gICAgc3dpdGNoIChuYW1lKSB7XG4gICAgICBjYXNlICdwcm9maWxlJzogcmV0dXJuIHRoaXMucHJvZmlsZURyYXdlcjtcbiAgICAgIGNhc2UgJ25vdGlmaWNhdGlvbic6IHJldHVybiB0aGlzLm5vdGlmaWNhdGlvbkRyYXdlcjtcbiAgICAgIGNhc2UgJ3RvZG8nOiByZXR1cm4gdGhpcy50b2RvRHJhd2VyO1xuICAgICAgY2FzZSAnbmV3VG9kbyc6IHJldHVybiB0aGlzLm5ld1RvZG9EcmF3ZXI7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBzZXR1cExpc3RlbmVycygpOiB2b2lkIHtcbiAgICAvLyBQcm9maWxlIGRyYXdlciB0cmlnZ2Vyc1xuICAgIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdwcm9maWxlVHJpZ2dlcicpXG4gICAgICA/LmFkZEV2ZW50TGlzdGVuZXIoJ2NsaWNrJywgKCkgPT4gdGhpcy5vcGVuUHJvZmlsZSgpKTtcbiAgICBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnZHJhd2VyQ2xvc2UnKVxuICAgICAgPy5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsICgpID0+IHRoaXMuY2xvc2UoJ3Byb2ZpbGUnKSk7XG5cbiAgICAvLyBOb3RpZmljYXRpb24gZHJhd2VyIHRyaWdnZXJzXG4gICAgZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ25vdGlmaWNhdGlvbnNCdG4nKVxuICAgICAgPy5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsICgpID0+IHRoaXMub3Blbk5vdGlmaWNhdGlvbigpKTtcbiAgICBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnbm90aWZpY2F0aW9uRHJhd2VyQ2xvc2UnKVxuICAgICAgPy5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsICgpID0+IHRoaXMuY2xvc2UoJ25vdGlmaWNhdGlvbicpKTtcbiAgICBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnbWFya0FsbFJlYWQnKVxuICAgICAgPy5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsICgpID0+IHRoaXMubWFya0FsbE5vdGlmaWNhdGlvbnNSZWFkKCkpO1xuXG4gICAgLy8gVG9kbyBkcmF3ZXIgdHJpZ2dlcnNcbiAgICBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnb3BlblRvZG9EcmF3ZXInKVxuICAgICAgPy5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsICgpID0+IHRoaXMub3BlblRvZG8oKSk7XG4gICAgZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ3RvZG9EcmF3ZXJCYWNrJylcbiAgICAgID8uYWRkRXZlbnRMaXN0ZW5lcignY2xpY2snLCAoKSA9PiB0aGlzLmNsb3NlVG9kbygpKTtcblxuICAgIC8vIE5ldyB0b2RvIGRyYXdlciB0cmlnZ2Vyc1xuICAgIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdhZGRUb2RvQnRuJylcbiAgICAgID8uYWRkRXZlbnRMaXN0ZW5lcignY2xpY2snLCAoKSA9PiB0aGlzLm9wZW5OZXdUb2RvKCkpO1xuICAgIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCduZXdUb2RvRHJhd2VyQmFjaycpXG4gICAgICA/LmFkZEV2ZW50TGlzdGVuZXIoJ2NsaWNrJywgKCkgPT4gdGhpcy5jbG9zZU5ld1RvZG8oKSk7XG4gICAgZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2NhbmNlbE5ld1RvZG8nKVxuICAgICAgPy5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsICgpID0+IHRoaXMuY2xvc2VOZXdUb2RvKCkpO1xuICAgIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdzYXZlTmV3VG9kbycpXG4gICAgICA/LmFkZEV2ZW50TGlzdGVuZXIoJ2NsaWNrJywgKCkgPT4gdGhpcy5jbG9zZU5ld1RvZG8oKSk7XG5cbiAgICAvLyBPdmVybGF5IGNsaWNrIGNsb3NlcyBhbGxcbiAgICB0aGlzLm92ZXJsYXk/LmFkZEV2ZW50TGlzdGVuZXIoJ2NsaWNrJywgKCkgPT4gdGhpcy5jbG9zZUFsbCgpKTtcblxuICAgIC8vIEVzY2FwZSBrZXkgY2xvc2VzIGFsbFxuICAgIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ2tleWRvd24nLCAoZTogS2V5Ym9hcmRFdmVudCkgPT4ge1xuICAgICAgaWYgKGUua2V5ID09PSAnRXNjYXBlJykgdGhpcy5jbG9zZUFsbCgpO1xuICAgIH0pO1xuXG4gICAgLy8gVG9kbyBpbnRlcmFjdGlvbnNcbiAgICB0aGlzLnRvZG9EcmF3ZXI/LmFkZEV2ZW50TGlzdGVuZXIoJ2NsaWNrJywgKGUpID0+IHRoaXMuaGFuZGxlVG9kb0NsaWNrKGUpKTtcblxuICAgIC8vIFZpc2liaWxpdHkgb3B0aW9uc1xuICAgIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ2NsaWNrJywgKGUpID0+IHRoaXMuaGFuZGxlVmlzaWJpbGl0eUNsaWNrKGUpKTtcbiAgfVxuXG4gIHByaXZhdGUgaGFuZGxlVG9kb0NsaWNrKGU6IEV2ZW50KTogdm9pZCB7XG4gICAgY29uc3QgdGFyZ2V0ID0gZS50YXJnZXQgYXMgSFRNTEVsZW1lbnQ7XG4gICAgY29uc3QgdG9kb0l0ZW0gPSB0YXJnZXQuY2xvc2VzdDxIVE1MRWxlbWVudD4oJ3N3cC10b2RvLWl0ZW0nKTtcbiAgICBjb25zdCBjaGVja2JveCA9IHRhcmdldC5jbG9zZXN0PEhUTUxFbGVtZW50Pignc3dwLXRvZG8tY2hlY2tib3gnKTtcblxuICAgIGlmIChjaGVja2JveCAmJiB0b2RvSXRlbSkge1xuICAgICAgY29uc3QgaXNDb21wbGV0ZWQgPSB0b2RvSXRlbS5kYXRhc2V0LmNvbXBsZXRlZCA9PT0gJ3RydWUnO1xuICAgICAgaWYgKGlzQ29tcGxldGVkKSB7XG4gICAgICAgIHRvZG9JdGVtLnJlbW92ZUF0dHJpYnV0ZSgnZGF0YS1jb21wbGV0ZWQnKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRvZG9JdGVtLmRhdGFzZXQuY29tcGxldGVkID0gJ3RydWUnO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIFRvZ2dsZSBzZWN0aW9uIGNvbGxhcHNlXG4gICAgY29uc3Qgc2VjdGlvbkhlYWRlciA9IHRhcmdldC5jbG9zZXN0PEhUTUxFbGVtZW50Pignc3dwLXRvZG8tc2VjdGlvbi1oZWFkZXInKTtcbiAgICBpZiAoc2VjdGlvbkhlYWRlcikge1xuICAgICAgY29uc3Qgc2VjdGlvbiA9IHNlY3Rpb25IZWFkZXIuY2xvc2VzdDxIVE1MRWxlbWVudD4oJ3N3cC10b2RvLXNlY3Rpb24nKTtcbiAgICAgIHNlY3Rpb24/LmNsYXNzTGlzdC50b2dnbGUoJ2NvbGxhcHNlZCcpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgaGFuZGxlVmlzaWJpbGl0eUNsaWNrKGU6IEV2ZW50KTogdm9pZCB7XG4gICAgY29uc3QgdGFyZ2V0ID0gZS50YXJnZXQgYXMgSFRNTEVsZW1lbnQ7XG4gICAgY29uc3Qgb3B0aW9uID0gdGFyZ2V0LmNsb3Nlc3Q8SFRNTEVsZW1lbnQ+KCdzd3AtdmlzaWJpbGl0eS1vcHRpb24nKTtcblxuICAgIGlmIChvcHRpb24pIHtcbiAgICAgIGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3JBbGw8SFRNTEVsZW1lbnQ+KCdzd3AtdmlzaWJpbGl0eS1vcHRpb24nKVxuICAgICAgICAuZm9yRWFjaChvID0+IG8uY2xhc3NMaXN0LnJlbW92ZSgnYWN0aXZlJykpO1xuICAgICAgb3B0aW9uLmNsYXNzTGlzdC5hZGQoJ2FjdGl2ZScpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBTZXR1cCBnZW5lcmljIGRyYXdlciB0cmlnZ2VycyBhbmQgY2xvc2UgYnV0dG9uc1xuICAgKiBVc2VzIGRhdGEtZHJhd2VyLXRyaWdnZXI9XCJkcmF3ZXItaWRcIiBhbmQgZGF0YS1kcmF3ZXItY2xvc2UgYXR0cmlidXRlc1xuICAgKi9cbiAgcHJpdmF0ZSBzZXR1cEdlbmVyaWNEcmF3ZXJzKCk6IHZvaWQge1xuICAgIC8vIEhhbmRsZSBkcmF3ZXIgdHJpZ2dlcnNcbiAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsIChlOiBFdmVudCkgPT4ge1xuICAgICAgY29uc3QgdGFyZ2V0ID0gZS50YXJnZXQgYXMgSFRNTEVsZW1lbnQ7XG4gICAgICBjb25zdCB0cmlnZ2VyID0gdGFyZ2V0LmNsb3Nlc3Q8SFRNTEVsZW1lbnQ+KCdbZGF0YS1kcmF3ZXItdHJpZ2dlcl0nKTtcblxuICAgICAgaWYgKHRyaWdnZXIpIHtcbiAgICAgICAgY29uc3QgZHJhd2VySWQgPSB0cmlnZ2VyLmRhdGFzZXQuZHJhd2VyVHJpZ2dlcjtcbiAgICAgICAgaWYgKGRyYXdlcklkKSB7XG4gICAgICAgICAgdGhpcy5vcGVuR2VuZXJpY0RyYXdlcihkcmF3ZXJJZCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9KTtcblxuICAgIC8vIEhhbmRsZSBkcmF3ZXIgY2xvc2UgYnV0dG9uc1xuICAgIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ2NsaWNrJywgKGU6IEV2ZW50KSA9PiB7XG4gICAgICBjb25zdCB0YXJnZXQgPSBlLnRhcmdldCBhcyBIVE1MRWxlbWVudDtcbiAgICAgIGNvbnN0IGNsb3NlQnRuID0gdGFyZ2V0LmNsb3Nlc3Q8SFRNTEVsZW1lbnQ+KCdbZGF0YS1kcmF3ZXItY2xvc2VdJyk7XG5cbiAgICAgIGlmIChjbG9zZUJ0bikge1xuICAgICAgICB0aGlzLmNsb3NlR2VuZXJpY0RyYXdlcigpO1xuICAgICAgICB0aGlzLm92ZXJsYXk/LmNsYXNzTGlzdC5yZW1vdmUoJ2FjdGl2ZScpO1xuICAgICAgICBkb2N1bWVudC5ib2R5LnN0eWxlLm92ZXJmbG93ID0gJyc7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cbn1cbiIsICIvKipcbiAqIFRoZW1lIENvbnRyb2xsZXJcbiAqXG4gKiBIYW5kbGVzIGRhcmsvbGlnaHQgbW9kZSBzd2l0Y2hpbmcgYW5kIHN5c3RlbSBwcmVmZXJlbmNlIGRldGVjdGlvblxuICovXG5cbmV4cG9ydCB0eXBlIFRoZW1lID0gJ2xpZ2h0JyB8ICdkYXJrJyB8ICdzeXN0ZW0nO1xuXG5leHBvcnQgY2xhc3MgVGhlbWVDb250cm9sbGVyIHtcbiAgcHJpdmF0ZSBzdGF0aWMgcmVhZG9ubHkgU1RPUkFHRV9LRVkgPSAndGhlbWUtcHJlZmVyZW5jZSc7XG4gIHByaXZhdGUgc3RhdGljIHJlYWRvbmx5IERBUktfQ0xBU1MgPSAnZGFyay1tb2RlJztcbiAgcHJpdmF0ZSBzdGF0aWMgcmVhZG9ubHkgTElHSFRfQ0xBU1MgPSAnbGlnaHQtbW9kZSc7XG5cbiAgcHJpdmF0ZSByb290OiBIVE1MRWxlbWVudDtcbiAgcHJpdmF0ZSB0aGVtZU9wdGlvbnM6IE5vZGVMaXN0T2Y8SFRNTEVsZW1lbnQ+O1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHRoaXMucm9vdCA9IGRvY3VtZW50LmRvY3VtZW50RWxlbWVudDtcbiAgICB0aGlzLnRoZW1lT3B0aW9ucyA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3JBbGw8SFRNTEVsZW1lbnQ+KCdzd3AtdGhlbWUtb3B0aW9uJyk7XG5cbiAgICB0aGlzLmFwcGx5VGhlbWUodGhpcy5jdXJyZW50KTtcbiAgICB0aGlzLnVwZGF0ZVVJKCk7XG4gICAgdGhpcy5zZXR1cExpc3RlbmVycygpO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCB0aGUgY3VycmVudCB0aGVtZSBzZXR0aW5nXG4gICAqL1xuICBnZXQgY3VycmVudCgpOiBUaGVtZSB7XG4gICAgY29uc3Qgc3RvcmVkID0gbG9jYWxTdG9yYWdlLmdldEl0ZW0oVGhlbWVDb250cm9sbGVyLlNUT1JBR0VfS0VZKSBhcyBUaGVtZSB8IG51bGw7XG4gICAgaWYgKHN0b3JlZCA9PT0gJ2RhcmsnIHx8IHN0b3JlZCA9PT0gJ2xpZ2h0JyB8fCBzdG9yZWQgPT09ICdzeXN0ZW0nKSB7XG4gICAgICByZXR1cm4gc3RvcmVkO1xuICAgIH1cbiAgICByZXR1cm4gJ3N5c3RlbSc7XG4gIH1cblxuICAvKipcbiAgICogQ2hlY2sgaWYgZGFyayBtb2RlIGlzIGN1cnJlbnRseSBhY3RpdmVcbiAgICovXG4gIGdldCBpc0RhcmsoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMucm9vdC5jbGFzc0xpc3QuY29udGFpbnMoVGhlbWVDb250cm9sbGVyLkRBUktfQ0xBU1MpIHx8XG4gICAgICAodGhpcy5zeXN0ZW1QcmVmZXJzRGFyayAmJiAhdGhpcy5yb290LmNsYXNzTGlzdC5jb250YWlucyhUaGVtZUNvbnRyb2xsZXIuTElHSFRfQ0xBU1MpKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDaGVjayBpZiBzeXN0ZW0gcHJlZmVycyBkYXJrIG1vZGVcbiAgICovXG4gIGdldCBzeXN0ZW1QcmVmZXJzRGFyaygpOiBib29sZWFuIHtcbiAgICByZXR1cm4gd2luZG93Lm1hdGNoTWVkaWEoJyhwcmVmZXJzLWNvbG9yLXNjaGVtZTogZGFyayknKS5tYXRjaGVzO1xuICB9XG5cbiAgLyoqXG4gICAqIFNldCB0aGVtZSBhbmQgcGVyc2lzdCBwcmVmZXJlbmNlXG4gICAqL1xuICBzZXQodGhlbWU6IFRoZW1lKTogdm9pZCB7XG4gICAgbG9jYWxTdG9yYWdlLnNldEl0ZW0oVGhlbWVDb250cm9sbGVyLlNUT1JBR0VfS0VZLCB0aGVtZSk7XG4gICAgdGhpcy5hcHBseVRoZW1lKHRoZW1lKTtcbiAgICB0aGlzLnVwZGF0ZVVJKCk7XG4gIH1cblxuICAvKipcbiAgICogVG9nZ2xlIGJldHdlZW4gbGlnaHQgYW5kIGRhcmsgdGhlbWVzXG4gICAqL1xuICB0b2dnbGUoKTogdm9pZCB7XG4gICAgdGhpcy5zZXQodGhpcy5pc0RhcmsgPyAnbGlnaHQnIDogJ2RhcmsnKTtcbiAgfVxuXG4gIHByaXZhdGUgYXBwbHlUaGVtZSh0aGVtZTogVGhlbWUpOiB2b2lkIHtcbiAgICB0aGlzLnJvb3QuY2xhc3NMaXN0LnJlbW92ZShUaGVtZUNvbnRyb2xsZXIuREFSS19DTEFTUywgVGhlbWVDb250cm9sbGVyLkxJR0hUX0NMQVNTKTtcblxuICAgIGlmICh0aGVtZSA9PT0gJ2RhcmsnKSB7XG4gICAgICB0aGlzLnJvb3QuY2xhc3NMaXN0LmFkZChUaGVtZUNvbnRyb2xsZXIuREFSS19DTEFTUyk7XG4gICAgfSBlbHNlIGlmICh0aGVtZSA9PT0gJ2xpZ2h0Jykge1xuICAgICAgdGhpcy5yb290LmNsYXNzTGlzdC5hZGQoVGhlbWVDb250cm9sbGVyLkxJR0hUX0NMQVNTKTtcbiAgICB9XG4gICAgLy8gJ3N5c3RlbScgbGVhdmVzIGJvdGggY2xhc3NlcyBvZmYsIGxldHRpbmcgQ1NTIG1lZGlhIHF1ZXJ5IGhhbmRsZSBpdFxuICB9XG5cbiAgcHJpdmF0ZSB1cGRhdGVVSSgpOiB2b2lkIHtcbiAgICBpZiAoIXRoaXMudGhlbWVPcHRpb25zKSByZXR1cm47XG5cbiAgICBjb25zdCBkYXJrQWN0aXZlID0gdGhpcy5pc0Rhcms7XG5cbiAgICB0aGlzLnRoZW1lT3B0aW9ucy5mb3JFYWNoKG9wdGlvbiA9PiB7XG4gICAgICBjb25zdCB0aGVtZSA9IG9wdGlvbi5kYXRhc2V0LnRoZW1lIGFzIFRoZW1lO1xuICAgICAgY29uc3QgaXNBY3RpdmUgPSAodGhlbWUgPT09ICdkYXJrJyAmJiBkYXJrQWN0aXZlKSB8fCAodGhlbWUgPT09ICdsaWdodCcgJiYgIWRhcmtBY3RpdmUpO1xuICAgICAgb3B0aW9uLmNsYXNzTGlzdC50b2dnbGUoJ2FjdGl2ZScsIGlzQWN0aXZlKTtcbiAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgc2V0dXBMaXN0ZW5lcnMoKTogdm9pZCB7XG4gICAgLy8gVGhlbWUgb3B0aW9uIGNsaWNrc1xuICAgIHRoaXMudGhlbWVPcHRpb25zLmZvckVhY2gob3B0aW9uID0+IHtcbiAgICAgIG9wdGlvbi5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsIChlKSA9PiB0aGlzLmhhbmRsZU9wdGlvbkNsaWNrKGUpKTtcbiAgICB9KTtcblxuICAgIC8vIFN5c3RlbSB0aGVtZSBjaGFuZ2VzXG4gICAgd2luZG93Lm1hdGNoTWVkaWEoJyhwcmVmZXJzLWNvbG9yLXNjaGVtZTogZGFyayknKVxuICAgICAgLmFkZEV2ZW50TGlzdGVuZXIoJ2NoYW5nZScsICgpID0+IHRoaXMuaGFuZGxlU3lzdGVtQ2hhbmdlKCkpO1xuICB9XG5cbiAgcHJpdmF0ZSBoYW5kbGVPcHRpb25DbGljayhlOiBFdmVudCk6IHZvaWQge1xuICAgIGNvbnN0IHRhcmdldCA9IGUudGFyZ2V0IGFzIEhUTUxFbGVtZW50O1xuICAgIGNvbnN0IG9wdGlvbiA9IHRhcmdldC5jbG9zZXN0PEhUTUxFbGVtZW50Pignc3dwLXRoZW1lLW9wdGlvbicpO1xuXG4gICAgaWYgKG9wdGlvbikge1xuICAgICAgY29uc3QgdGhlbWUgPSBvcHRpb24uZGF0YXNldC50aGVtZSBhcyBUaGVtZTtcbiAgICAgIGlmICh0aGVtZSkge1xuICAgICAgICB0aGlzLnNldCh0aGVtZSk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBoYW5kbGVTeXN0ZW1DaGFuZ2UoKTogdm9pZCB7XG4gICAgLy8gT25seSByZWFjdCB0byBzeXN0ZW0gY2hhbmdlcyBpZiB3ZSdyZSB1c2luZyBzeXN0ZW0gcHJlZmVyZW5jZVxuICAgIGlmICh0aGlzLmN1cnJlbnQgPT09ICdzeXN0ZW0nKSB7XG4gICAgICB0aGlzLnVwZGF0ZVVJKCk7XG4gICAgfVxuICB9XG59XG4iLCAiLyoqXG4gKiBTZWFyY2ggQ29udHJvbGxlclxuICpcbiAqIEhhbmRsZXMgZ2xvYmFsIHNlYXJjaCBmdW5jdGlvbmFsaXR5IGFuZCBrZXlib2FyZCBzaG9ydGN1dHNcbiAqL1xuXG5leHBvcnQgY2xhc3MgU2VhcmNoQ29udHJvbGxlciB7XG4gIHByaXZhdGUgaW5wdXQ6IEhUTUxJbnB1dEVsZW1lbnQgfCBudWxsID0gbnVsbDtcbiAgcHJpdmF0ZSBjb250YWluZXI6IEhUTUxFbGVtZW50IHwgbnVsbCA9IG51bGw7XG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgdGhpcy5pbnB1dCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdnbG9iYWxTZWFyY2gnKSBhcyBIVE1MSW5wdXRFbGVtZW50IHwgbnVsbDtcbiAgICB0aGlzLmNvbnRhaW5lciA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3I8SFRNTEVsZW1lbnQ+KCdzd3AtdG9wYmFyLXNlYXJjaCcpO1xuXG4gICAgdGhpcy5zZXR1cExpc3RlbmVycygpO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCBjdXJyZW50IHNlYXJjaCB2YWx1ZVxuICAgKi9cbiAgZ2V0IHZhbHVlKCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMuaW5wdXQ/LnZhbHVlID8/ICcnO1xuICB9XG5cbiAgLyoqXG4gICAqIFNldCBzZWFyY2ggdmFsdWVcbiAgICovXG4gIHNldCB2YWx1ZSh2YWw6IHN0cmluZykge1xuICAgIGlmICh0aGlzLmlucHV0KSB7XG4gICAgICB0aGlzLmlucHV0LnZhbHVlID0gdmFsO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBGb2N1cyB0aGUgc2VhcmNoIGlucHV0XG4gICAqL1xuICBmb2N1cygpOiB2b2lkIHtcbiAgICB0aGlzLmlucHV0Py5mb2N1cygpO1xuICB9XG5cbiAgLyoqXG4gICAqIEJsdXIgdGhlIHNlYXJjaCBpbnB1dFxuICAgKi9cbiAgYmx1cigpOiB2b2lkIHtcbiAgICB0aGlzLmlucHV0Py5ibHVyKCk7XG4gIH1cblxuICAvKipcbiAgICogQ2xlYXIgdGhlIHNlYXJjaCBpbnB1dFxuICAgKi9cbiAgY2xlYXIoKTogdm9pZCB7XG4gICAgdGhpcy52YWx1ZSA9ICcnO1xuICB9XG5cbiAgcHJpdmF0ZSBzZXR1cExpc3RlbmVycygpOiB2b2lkIHtcbiAgICAvLyBLZXlib2FyZCBzaG9ydGN1dHNcbiAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdrZXlkb3duJywgKGUpID0+IHRoaXMuaGFuZGxlS2V5Ym9hcmQoZSkpO1xuXG4gICAgLy8gSW5wdXQgaGFuZGxlcnNcbiAgICBpZiAodGhpcy5pbnB1dCkge1xuICAgICAgdGhpcy5pbnB1dC5hZGRFdmVudExpc3RlbmVyKCdpbnB1dCcsIChlKSA9PiB0aGlzLmhhbmRsZUlucHV0KGUpKTtcblxuICAgICAgLy8gUHJldmVudCBmb3JtIHN1Ym1pc3Npb24gaWYgd3JhcHBlZCBpbiBmb3JtXG4gICAgICBjb25zdCBmb3JtID0gdGhpcy5pbnB1dC5jbG9zZXN0KCdmb3JtJyk7XG4gICAgICBmb3JtPy5hZGRFdmVudExpc3RlbmVyKCdzdWJtaXQnLCAoZSkgPT4gdGhpcy5oYW5kbGVTdWJtaXQoZSkpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgaGFuZGxlS2V5Ym9hcmQoZTogS2V5Ym9hcmRFdmVudCk6IHZvaWQge1xuICAgIC8vIENtZC9DdHJsICsgSyB0byBmb2N1cyBzZWFyY2hcbiAgICBpZiAoKGUubWV0YUtleSB8fCBlLmN0cmxLZXkpICYmIGUua2V5ID09PSAnaycpIHtcbiAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgIHRoaXMuZm9jdXMoKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyBFc2NhcGUgdG8gYmx1ciBzZWFyY2ggd2hlbiBmb2N1c2VkXG4gICAgaWYgKGUua2V5ID09PSAnRXNjYXBlJyAmJiBkb2N1bWVudC5hY3RpdmVFbGVtZW50ID09PSB0aGlzLmlucHV0KSB7XG4gICAgICB0aGlzLmJsdXIoKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGhhbmRsZUlucHV0KGU6IEV2ZW50KTogdm9pZCB7XG4gICAgY29uc3QgdGFyZ2V0ID0gZS50YXJnZXQgYXMgSFRNTElucHV0RWxlbWVudDtcbiAgICBjb25zdCBxdWVyeSA9IHRhcmdldC52YWx1ZS50cmltKCk7XG5cbiAgICAvLyBFbWl0IGN1c3RvbSBldmVudCBmb3Igc2VhcmNoXG4gICAgZG9jdW1lbnQuZGlzcGF0Y2hFdmVudChuZXcgQ3VzdG9tRXZlbnQoJ2FwcDpzZWFyY2gnLCB7XG4gICAgICBkZXRhaWw6IHsgcXVlcnkgfSxcbiAgICAgIGJ1YmJsZXM6IHRydWVcbiAgICB9KSk7XG4gIH1cblxuICBwcml2YXRlIGhhbmRsZVN1Ym1pdChlOiBFdmVudCk6IHZvaWQge1xuICAgIGUucHJldmVudERlZmF1bHQoKTtcblxuICAgIGNvbnN0IHF1ZXJ5ID0gdGhpcy52YWx1ZS50cmltKCk7XG4gICAgaWYgKCFxdWVyeSkgcmV0dXJuO1xuXG4gICAgLy8gRW1pdCBjdXN0b20gZXZlbnQgZm9yIHNlYXJjaCBzdWJtaXRcbiAgICBkb2N1bWVudC5kaXNwYXRjaEV2ZW50KG5ldyBDdXN0b21FdmVudCgnYXBwOnNlYXJjaC1zdWJtaXQnLCB7XG4gICAgICBkZXRhaWw6IHsgcXVlcnkgfSxcbiAgICAgIGJ1YmJsZXM6IHRydWVcbiAgICB9KSk7XG4gIH1cbn1cbiIsICIvKipcbiAqIExvY2sgU2NyZWVuIENvbnRyb2xsZXJcbiAqXG4gKiBIYW5kbGVzIFBJTi1iYXNlZCBsb2NrIHNjcmVlbiBmdW5jdGlvbmFsaXR5XG4gKi9cblxuaW1wb3J0IHsgRHJhd2VyQ29udHJvbGxlciB9IGZyb20gJy4vZHJhd2Vycyc7XG5cbmV4cG9ydCBjbGFzcyBMb2NrU2NyZWVuQ29udHJvbGxlciB7XG4gIHByaXZhdGUgc3RhdGljIHJlYWRvbmx5IENPUlJFQ1RfUElOID0gJzEyMzQnOyAvLyBEZW1vIFBJTlxuXG4gIHByaXZhdGUgbG9ja1NjcmVlbjogSFRNTEVsZW1lbnQgfCBudWxsID0gbnVsbDtcbiAgcHJpdmF0ZSBwaW5JbnB1dDogSFRNTEVsZW1lbnQgfCBudWxsID0gbnVsbDtcbiAgcHJpdmF0ZSBwaW5LZXlwYWQ6IEhUTUxFbGVtZW50IHwgbnVsbCA9IG51bGw7XG4gIHByaXZhdGUgbG9ja1RpbWVFbDogSFRNTEVsZW1lbnQgfCBudWxsID0gbnVsbDtcbiAgcHJpdmF0ZSBwaW5EaWdpdHM6IE5vZGVMaXN0T2Y8SFRNTEVsZW1lbnQ+IHwgbnVsbCA9IG51bGw7XG4gIHByaXZhdGUgY3VycmVudFBpbiA9ICcnO1xuICBwcml2YXRlIGRyYXdlcnM6IERyYXdlckNvbnRyb2xsZXIgfCBudWxsID0gbnVsbDtcblxuICBjb25zdHJ1Y3RvcihkcmF3ZXJzPzogRHJhd2VyQ29udHJvbGxlcikge1xuICAgIHRoaXMuZHJhd2VycyA9IGRyYXdlcnMgPz8gbnVsbDtcbiAgICB0aGlzLmxvY2tTY3JlZW4gPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnbG9ja1NjcmVlbicpO1xuICAgIHRoaXMucGluSW5wdXQgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgncGluSW5wdXQnKTtcbiAgICB0aGlzLnBpbktleXBhZCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdwaW5LZXlwYWQnKTtcbiAgICB0aGlzLmxvY2tUaW1lRWwgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnbG9ja1RpbWUnKTtcbiAgICB0aGlzLnBpbkRpZ2l0cyA9IHRoaXMucGluSW5wdXQ/LnF1ZXJ5U2VsZWN0b3JBbGw8SFRNTEVsZW1lbnQ+KCdzd3AtcGluLWRpZ2l0JykgPz8gbnVsbDtcblxuICAgIHRoaXMuc2V0dXBMaXN0ZW5lcnMoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDaGVjayBpZiBsb2NrIHNjcmVlbiBpcyBhY3RpdmVcbiAgICovXG4gIGdldCBpc0FjdGl2ZSgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5sb2NrU2NyZWVuPy5jbGFzc0xpc3QuY29udGFpbnMoJ2FjdGl2ZScpID8/IGZhbHNlO1xuICB9XG5cbiAgLyoqXG4gICAqIFNob3cgdGhlIGxvY2sgc2NyZWVuXG4gICAqL1xuICBzaG93KCk6IHZvaWQge1xuICAgIHRoaXMuZHJhd2Vycz8uY2xvc2VBbGwoKTtcblxuICAgIGlmICh0aGlzLmxvY2tTY3JlZW4pIHtcbiAgICAgIHRoaXMubG9ja1NjcmVlbi5jbGFzc0xpc3QuYWRkKCdhY3RpdmUnKTtcbiAgICAgIGRvY3VtZW50LmJvZHkuc3R5bGUub3ZlcmZsb3cgPSAnaGlkZGVuJztcbiAgICB9XG5cbiAgICB0aGlzLmN1cnJlbnRQaW4gPSAnJztcbiAgICB0aGlzLnVwZGF0ZURpc3BsYXkoKTtcblxuICAgIC8vIFVwZGF0ZSBsb2NrIHRpbWVcbiAgICBpZiAodGhpcy5sb2NrVGltZUVsKSB7XG4gICAgICB0aGlzLmxvY2tUaW1lRWwudGV4dENvbnRlbnQgPSBgTFx1MDBFNXN0IGtsLiAke3RoaXMuZm9ybWF0VGltZSgpfWA7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEhpZGUgdGhlIGxvY2sgc2NyZWVuXG4gICAqL1xuICBoaWRlKCk6IHZvaWQge1xuICAgIGlmICh0aGlzLmxvY2tTY3JlZW4pIHtcbiAgICAgIHRoaXMubG9ja1NjcmVlbi5jbGFzc0xpc3QucmVtb3ZlKCdhY3RpdmUnKTtcbiAgICAgIGRvY3VtZW50LmJvZHkuc3R5bGUub3ZlcmZsb3cgPSAnJztcbiAgICB9XG5cbiAgICB0aGlzLmN1cnJlbnRQaW4gPSAnJztcbiAgICB0aGlzLnVwZGF0ZURpc3BsYXkoKTtcbiAgfVxuXG4gIHByaXZhdGUgZm9ybWF0VGltZSgpOiBzdHJpbmcge1xuICAgIGNvbnN0IG5vdyA9IG5ldyBEYXRlKCk7XG4gICAgY29uc3QgaG91cnMgPSBub3cuZ2V0SG91cnMoKS50b1N0cmluZygpLnBhZFN0YXJ0KDIsICcwJyk7XG4gICAgY29uc3QgbWludXRlcyA9IG5vdy5nZXRNaW51dGVzKCkudG9TdHJpbmcoKS5wYWRTdGFydCgyLCAnMCcpO1xuICAgIHJldHVybiBgJHtob3Vyc306JHttaW51dGVzfWA7XG4gIH1cblxuICBwcml2YXRlIHVwZGF0ZURpc3BsYXkoKTogdm9pZCB7XG4gICAgaWYgKCF0aGlzLnBpbkRpZ2l0cykgcmV0dXJuO1xuXG4gICAgdGhpcy5waW5EaWdpdHMuZm9yRWFjaCgoZGlnaXQsIGluZGV4KSA9PiB7XG4gICAgICBkaWdpdC5jbGFzc0xpc3QucmVtb3ZlKCdmaWxsZWQnLCAnZXJyb3InKTtcbiAgICAgIGlmIChpbmRleCA8IHRoaXMuY3VycmVudFBpbi5sZW5ndGgpIHtcbiAgICAgICAgZGlnaXQudGV4dENvbnRlbnQgPSAnXHUyMDIyJztcbiAgICAgICAgZGlnaXQuY2xhc3NMaXN0LmFkZCgnZmlsbGVkJyk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBkaWdpdC50ZXh0Q29udGVudCA9ICcnO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgcHJpdmF0ZSBzaG93RXJyb3IoKTogdm9pZCB7XG4gICAgaWYgKCF0aGlzLnBpbkRpZ2l0cykgcmV0dXJuO1xuXG4gICAgdGhpcy5waW5EaWdpdHMuZm9yRWFjaChkaWdpdCA9PiBkaWdpdC5jbGFzc0xpc3QuYWRkKCdlcnJvcicpKTtcblxuICAgIC8vIFNoYWtlIGFuaW1hdGlvblxuICAgIHRoaXMucGluSW5wdXQ/LmNsYXNzTGlzdC5hZGQoJ3NoYWtlJyk7XG5cbiAgICBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgIHRoaXMuY3VycmVudFBpbiA9ICcnO1xuICAgICAgdGhpcy51cGRhdGVEaXNwbGF5KCk7XG4gICAgICB0aGlzLnBpbklucHV0Py5jbGFzc0xpc3QucmVtb3ZlKCdzaGFrZScpO1xuICAgIH0sIDUwMCk7XG4gIH1cblxuICBwcml2YXRlIHZlcmlmeSgpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5jdXJyZW50UGluID09PSBMb2NrU2NyZWVuQ29udHJvbGxlci5DT1JSRUNUX1BJTikge1xuICAgICAgdGhpcy5oaWRlKCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuc2hvd0Vycm9yKCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBhZGREaWdpdChkaWdpdDogc3RyaW5nKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuY3VycmVudFBpbi5sZW5ndGggPj0gNCkgcmV0dXJuO1xuXG4gICAgdGhpcy5jdXJyZW50UGluICs9IGRpZ2l0O1xuICAgIHRoaXMudXBkYXRlRGlzcGxheSgpO1xuXG4gICAgLy8gQXV0by12ZXJpZnkgd2hlbiA0IGRpZ2l0cyBlbnRlcmVkXG4gICAgaWYgKHRoaXMuY3VycmVudFBpbi5sZW5ndGggPT09IDQpIHtcbiAgICAgIHNldFRpbWVvdXQoKCkgPT4gdGhpcy52ZXJpZnkoKSwgMjAwKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIHJlbW92ZURpZ2l0KCk6IHZvaWQge1xuICAgIGlmICh0aGlzLmN1cnJlbnRQaW4ubGVuZ3RoID09PSAwKSByZXR1cm47XG4gICAgdGhpcy5jdXJyZW50UGluID0gdGhpcy5jdXJyZW50UGluLnNsaWNlKDAsIC0xKTtcbiAgICB0aGlzLnVwZGF0ZURpc3BsYXkoKTtcbiAgfVxuXG4gIHByaXZhdGUgY2xlYXJQaW4oKTogdm9pZCB7XG4gICAgdGhpcy5jdXJyZW50UGluID0gJyc7XG4gICAgdGhpcy51cGRhdGVEaXNwbGF5KCk7XG4gIH1cblxuICBwcml2YXRlIHNldHVwTGlzdGVuZXJzKCk6IHZvaWQge1xuICAgIC8vIEtleXBhZCBjbGljayBoYW5kbGVyXG4gICAgdGhpcy5waW5LZXlwYWQ/LmFkZEV2ZW50TGlzdGVuZXIoJ2NsaWNrJywgKGUpID0+IHRoaXMuaGFuZGxlS2V5cGFkQ2xpY2soZSkpO1xuXG4gICAgLy8gS2V5Ym9hcmQgaW5wdXRcbiAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdrZXlkb3duJywgKGUpID0+IHRoaXMuaGFuZGxlS2V5Ym9hcmQoZSkpO1xuXG4gICAgLy8gTG9jayBidXR0b24gaW4gc2lkZWJhclxuICAgIGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3I8SFRNTEVsZW1lbnQ+KCdzd3Atc2lkZS1tZW51LWFjdGlvbi5sb2NrJylcbiAgICAgID8uYWRkRXZlbnRMaXN0ZW5lcignY2xpY2snLCAoKSA9PiB0aGlzLnNob3coKSk7XG4gIH1cblxuICBwcml2YXRlIGhhbmRsZUtleXBhZENsaWNrKGU6IEV2ZW50KTogdm9pZCB7XG4gICAgY29uc3QgdGFyZ2V0ID0gZS50YXJnZXQgYXMgSFRNTEVsZW1lbnQ7XG4gICAgY29uc3Qga2V5ID0gdGFyZ2V0LmNsb3Nlc3Q8SFRNTEVsZW1lbnQ+KCdzd3AtcGluLWtleScpO1xuXG4gICAgaWYgKCFrZXkpIHJldHVybjtcblxuICAgIGNvbnN0IGRpZ2l0ID0ga2V5LmRhdGFzZXQuZGlnaXQ7XG4gICAgY29uc3QgYWN0aW9uID0ga2V5LmRhdGFzZXQuYWN0aW9uO1xuXG4gICAgaWYgKGRpZ2l0KSB7XG4gICAgICB0aGlzLmFkZERpZ2l0KGRpZ2l0KTtcbiAgICB9IGVsc2UgaWYgKGFjdGlvbiA9PT0gJ2JhY2tzcGFjZScpIHtcbiAgICAgIHRoaXMucmVtb3ZlRGlnaXQoKTtcbiAgICB9IGVsc2UgaWYgKGFjdGlvbiA9PT0gJ2NsZWFyJykge1xuICAgICAgdGhpcy5jbGVhclBpbigpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgaGFuZGxlS2V5Ym9hcmQoZTogS2V5Ym9hcmRFdmVudCk6IHZvaWQge1xuICAgIGlmICghdGhpcy5pc0FjdGl2ZSkgcmV0dXJuO1xuXG4gICAgLy8gUHJldmVudCBkZWZhdWx0IHRvIGF2b2lkIG90aGVyIGludGVyYWN0aW9uc1xuICAgIGUucHJldmVudERlZmF1bHQoKTtcblxuICAgIGlmIChlLmtleSA+PSAnMCcgJiYgZS5rZXkgPD0gJzknKSB7XG4gICAgICB0aGlzLmFkZERpZ2l0KGUua2V5KTtcbiAgICB9IGVsc2UgaWYgKGUua2V5ID09PSAnQmFja3NwYWNlJykge1xuICAgICAgdGhpcy5yZW1vdmVEaWdpdCgpO1xuICAgIH0gZWxzZSBpZiAoZS5rZXkgPT09ICdFc2NhcGUnKSB7XG4gICAgICB0aGlzLmNsZWFyUGluKCk7XG4gICAgfVxuICB9XG59XG4iLCAiLyoqXG4gKiBDYXNoIENvbnRyb2xsZXJcbiAqXG4gKiBIYW5kbGVzIHRhYiBzd2l0Y2hpbmcsIGNhc2ggY2FsY3VsYXRpb25zLCBhbmQgZm9ybSBpbnRlcmFjdGlvbnNcbiAqIGZvciB0aGUgQ2FzaCBSZWdpc3RlciBwYWdlLlxuICovXG5cbmV4cG9ydCBjbGFzcyBDYXNoQ29udHJvbGxlciB7XG4gIC8vIEJhc2UgdmFsdWVzIChmcm9tIHN5c3RlbSAtIHdvdWxkIGNvbWUgZnJvbSBzZXJ2ZXIgaW4gcmVhbCBhcHApXG4gIHByaXZhdGUgcmVhZG9ubHkgc3RhcnRCYWxhbmNlID0gMjAwMDtcbiAgcHJpdmF0ZSByZWFkb25seSBjYXNoU2FsZXMgPSAzNTQwO1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHRoaXMuc2V0dXBUYWJzKCk7XG4gICAgdGhpcy5zZXR1cENhc2hDYWxjdWxhdGlvbigpO1xuICAgIHRoaXMuc2V0dXBDaGVja2JveFNlbGVjdGlvbigpO1xuICAgIHRoaXMuc2V0dXBBcHByb3ZhbENoZWNrYm94KCk7XG4gICAgdGhpcy5zZXR1cERhdGVGaWx0ZXJzKCk7XG4gICAgdGhpcy5zZXR1cFJvd1RvZ2dsZSgpO1xuICAgIHRoaXMuc2V0dXBEcmFmdFJvd0NsaWNrKCk7XG4gIH1cblxuICAvKipcbiAgICogU2V0dXAgdGFiIHN3aXRjaGluZyBmdW5jdGlvbmFsaXR5XG4gICAqL1xuICBwcml2YXRlIHNldHVwVGFicygpOiB2b2lkIHtcbiAgICBjb25zdCB0YWJzID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbDxIVE1MRWxlbWVudD4oJ3N3cC10YWJbZGF0YS10YWJdJyk7XG5cbiAgICB0YWJzLmZvckVhY2godGFiID0+IHtcbiAgICAgIHRhYi5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsICgpID0+IHtcbiAgICAgICAgY29uc3QgdGFyZ2V0VGFiID0gdGFiLmRhdGFzZXQudGFiO1xuICAgICAgICBpZiAodGFyZ2V0VGFiKSB7XG4gICAgICAgICAgdGhpcy5zd2l0Y2hUb1RhYih0YXJnZXRUYWIpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTd2l0Y2ggdG8gYSBzcGVjaWZpYyB0YWIgYnkgbmFtZVxuICAgKi9cbiAgcHJpdmF0ZSBzd2l0Y2hUb1RhYih0YXJnZXRUYWI6IHN0cmluZyk6IHZvaWQge1xuICAgIGNvbnN0IHRhYnMgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yQWxsPEhUTUxFbGVtZW50Pignc3dwLXRhYltkYXRhLXRhYl0nKTtcbiAgICBjb25zdCBjb250ZW50cyA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3JBbGw8SFRNTEVsZW1lbnQ+KCdzd3AtdGFiLWNvbnRlbnRbZGF0YS10YWJdJyk7XG4gICAgY29uc3Qgc3RhdHNCYXJzID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbDxIVE1MRWxlbWVudD4oJ3N3cC1jYXNoLXN0YXRzW2RhdGEtZm9yLXRhYl0nKTtcblxuICAgIC8vIFVwZGF0ZSB0YWIgc3RhdGVzXG4gICAgdGFicy5mb3JFYWNoKHQgPT4ge1xuICAgICAgaWYgKHQuZGF0YXNldC50YWIgPT09IHRhcmdldFRhYikge1xuICAgICAgICB0LmNsYXNzTGlzdC5hZGQoJ2FjdGl2ZScpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdC5jbGFzc0xpc3QucmVtb3ZlKCdhY3RpdmUnKTtcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIC8vIFVwZGF0ZSBjb250ZW50IHZpc2liaWxpdHlcbiAgICBjb250ZW50cy5mb3JFYWNoKGNvbnRlbnQgPT4ge1xuICAgICAgaWYgKGNvbnRlbnQuZGF0YXNldC50YWIgPT09IHRhcmdldFRhYikge1xuICAgICAgICBjb250ZW50LmNsYXNzTGlzdC5hZGQoJ2FjdGl2ZScpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY29udGVudC5jbGFzc0xpc3QucmVtb3ZlKCdhY3RpdmUnKTtcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIC8vIFVwZGF0ZSBzdGF0cyBiYXIgdmlzaWJpbGl0eVxuICAgIHN0YXRzQmFycy5mb3JFYWNoKHN0YXRzID0+IHtcbiAgICAgIGlmIChzdGF0cy5kYXRhc2V0LmZvclRhYiA9PT0gdGFyZ2V0VGFiKSB7XG4gICAgICAgIHN0YXRzLmNsYXNzTGlzdC5hZGQoJ2FjdGl2ZScpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgc3RhdHMuY2xhc3NMaXN0LnJlbW92ZSgnYWN0aXZlJyk7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogU2V0dXAgY2FzaCBjYWxjdWxhdGlvbiB3aXRoIHJlYWwtdGltZSB1cGRhdGVzXG4gICAqL1xuICBwcml2YXRlIHNldHVwQ2FzaENhbGN1bGF0aW9uKCk6IHZvaWQge1xuICAgIGNvbnN0IHBheW91dHNJbnB1dCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdwYXlvdXRzJykgYXMgSFRNTElucHV0RWxlbWVudDtcbiAgICBjb25zdCB0b0JhbmtJbnB1dCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCd0b0JhbmsnKSBhcyBIVE1MSW5wdXRFbGVtZW50O1xuICAgIGNvbnN0IGFjdHVhbENhc2hJbnB1dCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdhY3R1YWxDYXNoJykgYXMgSFRNTElucHV0RWxlbWVudDtcblxuICAgIGlmICghcGF5b3V0c0lucHV0IHx8ICF0b0JhbmtJbnB1dCB8fCAhYWN0dWFsQ2FzaElucHV0KSByZXR1cm47XG5cbiAgICBjb25zdCBjYWxjdWxhdGUgPSAoKSA9PiB0aGlzLmNhbGN1bGF0ZUNhc2gocGF5b3V0c0lucHV0LCB0b0JhbmtJbnB1dCwgYWN0dWFsQ2FzaElucHV0KTtcblxuICAgIHBheW91dHNJbnB1dC5hZGRFdmVudExpc3RlbmVyKCdpbnB1dCcsIGNhbGN1bGF0ZSk7XG4gICAgdG9CYW5rSW5wdXQuYWRkRXZlbnRMaXN0ZW5lcignaW5wdXQnLCBjYWxjdWxhdGUpO1xuICAgIGFjdHVhbENhc2hJbnB1dC5hZGRFdmVudExpc3RlbmVyKCdpbnB1dCcsIGNhbGN1bGF0ZSk7XG5cbiAgICAvLyBJbml0aWFsIGNhbGN1bGF0aW9uXG4gICAgY2FsY3VsYXRlKCk7XG4gIH1cblxuICAvKipcbiAgICogQ2FsY3VsYXRlIGV4cGVjdGVkIGNhc2ggYW5kIGRpZmZlcmVuY2VcbiAgICovXG4gIHByaXZhdGUgY2FsY3VsYXRlQ2FzaChcbiAgICBwYXlvdXRzSW5wdXQ6IEhUTUxJbnB1dEVsZW1lbnQsXG4gICAgdG9CYW5rSW5wdXQ6IEhUTUxJbnB1dEVsZW1lbnQsXG4gICAgYWN0dWFsQ2FzaElucHV0OiBIVE1MSW5wdXRFbGVtZW50XG4gICk6IHZvaWQge1xuICAgIGNvbnN0IHBheW91dHMgPSB0aGlzLnBhcnNlTnVtYmVyKHBheW91dHNJbnB1dC52YWx1ZSk7XG4gICAgY29uc3QgdG9CYW5rID0gdGhpcy5wYXJzZU51bWJlcih0b0JhbmtJbnB1dC52YWx1ZSk7XG4gICAgY29uc3QgYWN0dWFsID0gdGhpcy5wYXJzZU51bWJlcihhY3R1YWxDYXNoSW5wdXQudmFsdWUpO1xuXG4gICAgLy8gRXhwZWN0ZWQgPSBzdGFydCArIHNhbGVzIC0gcGF5b3V0cyAtIHRvIGJhbmtcbiAgICBjb25zdCBleHBlY3RlZENhc2ggPSB0aGlzLnN0YXJ0QmFsYW5jZSArIHRoaXMuY2FzaFNhbGVzIC0gcGF5b3V0cyAtIHRvQmFuaztcblxuICAgIGNvbnN0IGV4cGVjdGVkRWxlbWVudCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdleHBlY3RlZENhc2gnKTtcbiAgICBpZiAoZXhwZWN0ZWRFbGVtZW50KSB7XG4gICAgICBleHBlY3RlZEVsZW1lbnQudGV4dENvbnRlbnQgPSB0aGlzLmZvcm1hdE51bWJlcihleHBlY3RlZENhc2gpO1xuICAgIH1cblxuICAgIC8vIENhbGN1bGF0ZSBhbmQgZGlzcGxheSBkaWZmZXJlbmNlXG4gICAgdGhpcy51cGRhdGVEaWZmZXJlbmNlKGFjdHVhbCwgZXhwZWN0ZWRDYXNoLCBhY3R1YWxDYXNoSW5wdXQudmFsdWUpO1xuICB9XG5cbiAgLyoqXG4gICAqIFVwZGF0ZSBkaWZmZXJlbmNlIGJveCB3aXRoIGNvbG9yIGNvZGluZ1xuICAgKi9cbiAgcHJpdmF0ZSB1cGRhdGVEaWZmZXJlbmNlKGFjdHVhbDogbnVtYmVyLCBleHBlY3RlZDogbnVtYmVyLCByYXdWYWx1ZTogc3RyaW5nKTogdm9pZCB7XG4gICAgY29uc3QgYm94ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2RpZmZlcmVuY2VCb3gnKTtcbiAgICBjb25zdCB2YWx1ZSA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdkaWZmZXJlbmNlVmFsdWUnKTtcbiAgICBpZiAoIWJveCB8fCAhdmFsdWUpIHJldHVybjtcblxuICAgIGNvbnN0IGRpZmYgPSBhY3R1YWwgLSBleHBlY3RlZDtcblxuICAgIC8vIFJlbW92ZSBhbGwgc3RhdGUgY2xhc3Nlc1xuICAgIGJveC5jbGFzc0xpc3QucmVtb3ZlKCdwb3NpdGl2ZScsICduZWdhdGl2ZScsICduZXV0cmFsJyk7XG5cbiAgICBpZiAoYWN0dWFsID09PSAwICYmIHJhd1ZhbHVlID09PSAnJykge1xuICAgICAgLy8gTm8gaW5wdXQgeWV0XG4gICAgICB2YWx1ZS50ZXh0Q29udGVudCA9ICdcdTIwMTMga3InO1xuICAgICAgYm94LmNsYXNzTGlzdC5hZGQoJ25ldXRyYWwnKTtcbiAgICB9IGVsc2UgaWYgKGRpZmYgPiAwKSB7XG4gICAgICAvLyBNb3JlIGNhc2ggdGhhbiBleHBlY3RlZFxuICAgICAgdmFsdWUudGV4dENvbnRlbnQgPSAnKycgKyB0aGlzLmZvcm1hdE51bWJlcihkaWZmKSArICcga3InO1xuICAgICAgYm94LmNsYXNzTGlzdC5hZGQoJ3Bvc2l0aXZlJyk7XG4gICAgfSBlbHNlIGlmIChkaWZmIDwgMCkge1xuICAgICAgLy8gTGVzcyBjYXNoIHRoYW4gZXhwZWN0ZWRcbiAgICAgIHZhbHVlLnRleHRDb250ZW50ID0gdGhpcy5mb3JtYXROdW1iZXIoZGlmZikgKyAnIGtyJztcbiAgICAgIGJveC5jbGFzc0xpc3QuYWRkKCduZWdhdGl2ZScpO1xuICAgIH0gZWxzZSB7XG4gICAgICAvLyBFeGFjdCBtYXRjaFxuICAgICAgdmFsdWUudGV4dENvbnRlbnQgPSAnMCwwMCBrcic7XG4gICAgICBib3guY2xhc3NMaXN0LmFkZCgnbmV1dHJhbCcpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBTZXR1cCBjaGVja2JveCBzZWxlY3Rpb24gZm9yIHRhYmxlIHJvd3NcbiAgICovXG4gIHByaXZhdGUgc2V0dXBDaGVja2JveFNlbGVjdGlvbigpOiB2b2lkIHtcbiAgICBjb25zdCBzZWxlY3RBbGwgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnc2VsZWN0QWxsJykgYXMgSFRNTElucHV0RWxlbWVudDtcbiAgICBjb25zdCByb3dDaGVja2JveGVzID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbDxIVE1MSW5wdXRFbGVtZW50PignLnJvdy1zZWxlY3QnKTtcbiAgICBjb25zdCBleHBvcnRCdG4gPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnZXhwb3J0QnRuJykgYXMgSFRNTEJ1dHRvbkVsZW1lbnQ7XG4gICAgY29uc3Qgc2VsZWN0aW9uQ291bnQgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnc2VsZWN0aW9uQ291bnQnKTtcblxuICAgIGlmICghc2VsZWN0QWxsIHx8ICFleHBvcnRCdG4gfHwgIXNlbGVjdGlvbkNvdW50KSByZXR1cm47XG5cbiAgICBjb25zdCB1cGRhdGVTZWxlY3Rpb24gPSAoKSA9PiB7XG4gICAgICBjb25zdCBjaGVja2VkID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbDxIVE1MSW5wdXRFbGVtZW50PignLnJvdy1zZWxlY3Q6Y2hlY2tlZCcpO1xuICAgICAgY29uc3QgY291bnQgPSBjaGVja2VkLmxlbmd0aDtcblxuICAgICAgc2VsZWN0aW9uQ291bnQudGV4dENvbnRlbnQgPSBjb3VudCA9PT0gMCA/ICcwIHZhbGd0JyA6IGAke2NvdW50fSB2YWxndGA7XG4gICAgICBleHBvcnRCdG4uZGlzYWJsZWQgPSBjb3VudCA9PT0gMDtcblxuICAgICAgLy8gVXBkYXRlIHNlbGVjdCBhbGwgc3RhdGVcbiAgICAgIHNlbGVjdEFsbC5jaGVja2VkID0gY291bnQgPT09IHJvd0NoZWNrYm94ZXMubGVuZ3RoICYmIGNvdW50ID4gMDtcbiAgICAgIHNlbGVjdEFsbC5pbmRldGVybWluYXRlID0gY291bnQgPiAwICYmIGNvdW50IDwgcm93Q2hlY2tib3hlcy5sZW5ndGg7XG4gICAgfTtcblxuICAgIHNlbGVjdEFsbC5hZGRFdmVudExpc3RlbmVyKCdjaGFuZ2UnLCAoKSA9PiB7XG4gICAgICByb3dDaGVja2JveGVzLmZvckVhY2goY2IgPT4gY2IuY2hlY2tlZCA9IHNlbGVjdEFsbC5jaGVja2VkKTtcbiAgICAgIHVwZGF0ZVNlbGVjdGlvbigpO1xuICAgIH0pO1xuXG4gICAgcm93Q2hlY2tib3hlcy5mb3JFYWNoKGNiID0+IHtcbiAgICAgIGNiLmFkZEV2ZW50TGlzdGVuZXIoJ2NoYW5nZScsIHVwZGF0ZVNlbGVjdGlvbik7XG4gICAgICAvLyBTdG9wIGNsaWNrIGZyb20gYnViYmxpbmcgdG8gcm93XG4gICAgICBjYi5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsIGUgPT4gZS5zdG9wUHJvcGFnYXRpb24oKSk7XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogU2V0dXAgYXBwcm92YWwgY2hlY2tib3ggdG8gZW5hYmxlL2Rpc2FibGUgYXBwcm92ZSBidXR0b25cbiAgICovXG4gIHByaXZhdGUgc2V0dXBBcHByb3ZhbENoZWNrYm94KCk6IHZvaWQge1xuICAgIGNvbnN0IGNoZWNrYm94ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2NvbmZpcm1DaGVja2JveCcpIGFzIEhUTUxJbnB1dEVsZW1lbnQ7XG4gICAgY29uc3QgYXBwcm92ZUJ0biA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdhcHByb3ZlQnRuJykgYXMgSFRNTEJ1dHRvbkVsZW1lbnQ7XG5cbiAgICBpZiAoIWNoZWNrYm94IHx8ICFhcHByb3ZlQnRuKSByZXR1cm47XG5cbiAgICBjaGVja2JveC5hZGRFdmVudExpc3RlbmVyKCdjaGFuZ2UnLCAoKSA9PiB7XG4gICAgICBhcHByb3ZlQnRuLmRpc2FibGVkID0gIWNoZWNrYm94LmNoZWNrZWQ7XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogU2V0dXAgZGF0ZSBmaWx0ZXIgZGVmYXVsdHMgKGxhc3QgMzAgZGF5cylcbiAgICovXG4gIHByaXZhdGUgc2V0dXBEYXRlRmlsdGVycygpOiB2b2lkIHtcbiAgICBjb25zdCBkYXRlRnJvbSA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdkYXRlRnJvbScpIGFzIEhUTUxJbnB1dEVsZW1lbnQ7XG4gICAgY29uc3QgZGF0ZVRvID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2RhdGVUbycpIGFzIEhUTUxJbnB1dEVsZW1lbnQ7XG5cbiAgICBpZiAoIWRhdGVGcm9tIHx8ICFkYXRlVG8pIHJldHVybjtcblxuICAgIGNvbnN0IHRvZGF5ID0gbmV3IERhdGUoKTtcbiAgICBjb25zdCB0aGlydHlEYXlzQWdvID0gbmV3IERhdGUodG9kYXkpO1xuICAgIHRoaXJ0eURheXNBZ28uc2V0RGF0ZSh0b2RheS5nZXREYXRlKCkgLSAzMCk7XG5cbiAgICBkYXRlVG8udmFsdWUgPSB0aGlzLmZvcm1hdERhdGVJU08odG9kYXkpO1xuICAgIGRhdGVGcm9tLnZhbHVlID0gdGhpcy5mb3JtYXREYXRlSVNPKHRoaXJ0eURheXNBZ28pO1xuICB9XG5cbiAgLyoqXG4gICAqIEZvcm1hdCBudW1iZXIgYXMgRGFuaXNoIGN1cnJlbmN5XG4gICAqL1xuICBwcml2YXRlIGZvcm1hdE51bWJlcihudW06IG51bWJlcik6IHN0cmluZyB7XG4gICAgcmV0dXJuIG51bS50b0xvY2FsZVN0cmluZygnZGEtREsnLCB7XG4gICAgICBtaW5pbXVtRnJhY3Rpb25EaWdpdHM6IDIsXG4gICAgICBtYXhpbXVtRnJhY3Rpb25EaWdpdHM6IDJcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBQYXJzZSBEYW5pc2ggbnVtYmVyIGZvcm1hdFxuICAgKi9cbiAgcHJpdmF0ZSBwYXJzZU51bWJlcihzdHI6IHN0cmluZyk6IG51bWJlciB7XG4gICAgaWYgKCFzdHIpIHJldHVybiAwO1xuICAgIHJldHVybiBwYXJzZUZsb2F0KHN0ci5yZXBsYWNlKC9cXC4vZywgJycpLnJlcGxhY2UoJywnLCAnLicpKSB8fCAwO1xuICB9XG5cbiAgLyoqXG4gICAqIEZvcm1hdCBkYXRlIGFzIElTTyBzdHJpbmcgKFlZWVktTU0tREQpXG4gICAqL1xuICBwcml2YXRlIGZvcm1hdERhdGVJU08oZGF0ZTogRGF0ZSk6IHN0cmluZyB7XG4gICAgcmV0dXJuIGRhdGUudG9JU09TdHJpbmcoKS5zcGxpdCgnVCcpWzBdO1xuICB9XG5cbiAgLyoqXG4gICAqIFNldHVwIHJvdyB0b2dnbGUgZm9yIGV4cGFuZGFibGUgZGV0YWlsc1xuICAgKi9cbiAgcHJpdmF0ZSBzZXR1cFJvd1RvZ2dsZSgpOiB2b2lkIHtcbiAgICBjb25zdCByb3dzID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbDxIVE1MRWxlbWVudD4oJ3N3cC1jYXNoLXRhYmxlLXJvd1tkYXRhLWlkXTpub3QoLmRyYWZ0LXJvdyknKTtcblxuICAgIHJvd3MuZm9yRWFjaChyb3cgPT4ge1xuICAgICAgY29uc3Qgcm93SWQgPSByb3cuZ2V0QXR0cmlidXRlKCdkYXRhLWlkJyk7XG4gICAgICBpZiAoIXJvd0lkKSByZXR1cm47XG5cbiAgICAgIGNvbnN0IGRldGFpbCA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3I8SFRNTEVsZW1lbnQ+KGBzd3AtY2FzaC1yb3ctZGV0YWlsW2RhdGEtZm9yPVwiJHtyb3dJZH1cIl1gKTtcbiAgICAgIGlmICghZGV0YWlsKSByZXR1cm47XG5cbiAgICAgIHJvdy5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsIChlKSA9PiB7XG4gICAgICAgIC8vIERvbid0IHRvZ2dsZSBpZiBjbGlja2luZyBvbiBjaGVja2JveFxuICAgICAgICBpZiAoKGUudGFyZ2V0IGFzIEhUTUxFbGVtZW50KS5jbG9zZXN0KCdpbnB1dFt0eXBlPVwiY2hlY2tib3hcIl0nKSkgcmV0dXJuO1xuXG4gICAgICAgIGNvbnN0IGljb24gPSByb3cucXVlcnlTZWxlY3Rvcignc3dwLXJvdy10b2dnbGUgaScpO1xuICAgICAgICBjb25zdCBpc0V4cGFuZGVkID0gcm93LmNsYXNzTGlzdC5jb250YWlucygnZXhwYW5kZWQnKTtcblxuICAgICAgICAvLyBDbG9zZSBvdGhlciBleHBhbmRlZCByb3dzXG4gICAgICAgIGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3JBbGwoJ3N3cC1jYXNoLXRhYmxlLXJvdy5leHBhbmRlZCcpLmZvckVhY2gociA9PiB7XG4gICAgICAgICAgaWYgKHIgIT09IHJvdykge1xuICAgICAgICAgICAgY29uc3Qgb3RoZXJJZCA9IHIuZ2V0QXR0cmlidXRlKCdkYXRhLWlkJyk7XG4gICAgICAgICAgICBpZiAob3RoZXJJZCkge1xuICAgICAgICAgICAgICBjb25zdCBvdGhlckRldGFpbCA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3I8SFRNTEVsZW1lbnQ+KGBzd3AtY2FzaC1yb3ctZGV0YWlsW2RhdGEtZm9yPVwiJHtvdGhlcklkfVwiXWApO1xuICAgICAgICAgICAgICBjb25zdCBvdGhlckljb24gPSByLnF1ZXJ5U2VsZWN0b3IoJ3N3cC1yb3ctdG9nZ2xlIGknKTtcbiAgICAgICAgICAgICAgaWYgKG90aGVyRGV0YWlsICYmIG90aGVySWNvbikge1xuICAgICAgICAgICAgICAgIHRoaXMuY29sbGFwc2VSb3cociwgb3RoZXJEZXRhaWwsIG90aGVySWNvbiBhcyBIVE1MRWxlbWVudCk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuXG4gICAgICAgIC8vIFRvZ2dsZSBjdXJyZW50IHJvd1xuICAgICAgICBpZiAoaXNFeHBhbmRlZCkge1xuICAgICAgICAgIHRoaXMuY29sbGFwc2VSb3cocm93LCBkZXRhaWwsIGljb24pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRoaXMuZXhwYW5kUm93KHJvdywgZGV0YWlsLCBpY29uKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogRXhwYW5kIGEgcm93IHdpdGggYW5pbWF0aW9uXG4gICAqL1xuICBwcml2YXRlIGV4cGFuZFJvdyhyb3c6IEVsZW1lbnQsIGRldGFpbDogSFRNTEVsZW1lbnQsIGljb246IEVsZW1lbnQgfCBudWxsKTogdm9pZCB7XG4gICAgcm93LmNsYXNzTGlzdC5hZGQoJ2V4cGFuZGVkJyk7XG4gICAgZGV0YWlsLmNsYXNzTGlzdC5hZGQoJ2V4cGFuZGVkJyk7XG5cbiAgICAvLyBBbmltYXRlIGljb24gcm90YXRpb25cbiAgICBpY29uPy5hbmltYXRlKFtcbiAgICAgIHsgdHJhbnNmb3JtOiAncm90YXRlKDBkZWcpJyB9LFxuICAgICAgeyB0cmFuc2Zvcm06ICdyb3RhdGUoOTBkZWcpJyB9XG4gICAgXSwge1xuICAgICAgZHVyYXRpb246IDIwMCxcbiAgICAgIGVhc2luZzogJ2Vhc2Utb3V0JyxcbiAgICAgIGZpbGw6ICdmb3J3YXJkcydcbiAgICB9KTtcblxuICAgIC8vIEFuaW1hdGUgZGV0YWlsIGV4cGFuc2lvblxuICAgIGNvbnN0IGNvbnRlbnQgPSBkZXRhaWwucXVlcnlTZWxlY3Rvcignc3dwLXJvdy1kZXRhaWwtY29udGVudCcpIGFzIEhUTUxFbGVtZW50O1xuICAgIGlmIChjb250ZW50KSB7XG4gICAgICBjb25zdCBoZWlnaHQgPSBjb250ZW50Lm9mZnNldEhlaWdodDtcbiAgICAgIGRldGFpbC5hbmltYXRlKFtcbiAgICAgICAgeyBoZWlnaHQ6ICcwcHgnLCBvcGFjaXR5OiAwIH0sXG4gICAgICAgIHsgaGVpZ2h0OiBgJHtoZWlnaHR9cHhgLCBvcGFjaXR5OiAxIH1cbiAgICAgIF0sIHtcbiAgICAgICAgZHVyYXRpb246IDI1MCxcbiAgICAgICAgZWFzaW5nOiAnZWFzZS1vdXQnLFxuICAgICAgICBmaWxsOiAnZm9yd2FyZHMnXG4gICAgICB9KTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQ29sbGFwc2UgYSByb3cgd2l0aCBhbmltYXRpb25cbiAgICovXG4gIHByaXZhdGUgY29sbGFwc2VSb3cocm93OiBFbGVtZW50LCBkZXRhaWw6IEhUTUxFbGVtZW50LCBpY29uOiBFbGVtZW50IHwgbnVsbCk6IHZvaWQge1xuICAgIC8vIEFuaW1hdGUgaWNvbiByb3RhdGlvblxuICAgIGljb24/LmFuaW1hdGUoW1xuICAgICAgeyB0cmFuc2Zvcm06ICdyb3RhdGUoOTBkZWcpJyB9LFxuICAgICAgeyB0cmFuc2Zvcm06ICdyb3RhdGUoMGRlZyknIH1cbiAgICBdLCB7XG4gICAgICBkdXJhdGlvbjogMjAwLFxuICAgICAgZWFzaW5nOiAnZWFzZS1vdXQnLFxuICAgICAgZmlsbDogJ2ZvcndhcmRzJ1xuICAgIH0pO1xuXG4gICAgLy8gQW5pbWF0ZSBkZXRhaWwgY29sbGFwc2VcbiAgICBjb25zdCBjb250ZW50ID0gZGV0YWlsLnF1ZXJ5U2VsZWN0b3IoJ3N3cC1yb3ctZGV0YWlsLWNvbnRlbnQnKSBhcyBIVE1MRWxlbWVudDtcbiAgICBpZiAoY29udGVudCkge1xuICAgICAgY29uc3QgaGVpZ2h0ID0gY29udGVudC5vZmZzZXRIZWlnaHQ7XG4gICAgICBjb25zdCBhbmltYXRpb24gPSBkZXRhaWwuYW5pbWF0ZShbXG4gICAgICAgIHsgaGVpZ2h0OiBgJHtoZWlnaHR9cHhgLCBvcGFjaXR5OiAxIH0sXG4gICAgICAgIHsgaGVpZ2h0OiAnMHB4Jywgb3BhY2l0eTogMCB9XG4gICAgICBdLCB7XG4gICAgICAgIGR1cmF0aW9uOiAyMDAsXG4gICAgICAgIGVhc2luZzogJ2Vhc2Utb3V0JyxcbiAgICAgICAgZmlsbDogJ2ZvcndhcmRzJ1xuICAgICAgfSk7XG5cbiAgICAgIGFuaW1hdGlvbi5vbmZpbmlzaCA9ICgpID0+IHtcbiAgICAgICAgcm93LmNsYXNzTGlzdC5yZW1vdmUoJ2V4cGFuZGVkJyk7XG4gICAgICAgIGRldGFpbC5jbGFzc0xpc3QucmVtb3ZlKCdleHBhbmRlZCcpO1xuICAgICAgfTtcbiAgICB9IGVsc2Uge1xuICAgICAgcm93LmNsYXNzTGlzdC5yZW1vdmUoJ2V4cGFuZGVkJyk7XG4gICAgICBkZXRhaWwuY2xhc3NMaXN0LnJlbW92ZSgnZXhwYW5kZWQnKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogU2V0dXAgZHJhZnQgcm93IGNsaWNrIHRvIG5hdmlnYXRlIHRvIHJlY29uY2lsaWF0aW9uIHRhYlxuICAgKi9cbiAgcHJpdmF0ZSBzZXR1cERyYWZ0Um93Q2xpY2soKTogdm9pZCB7XG4gICAgY29uc3QgZHJhZnRSb3cgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yPEhUTUxFbGVtZW50Pignc3dwLWNhc2gtdGFibGUtcm93LmRyYWZ0LXJvdycpO1xuICAgIGlmICghZHJhZnRSb3cpIHJldHVybjtcblxuICAgIGRyYWZ0Um93LnN0eWxlLmN1cnNvciA9ICdwb2ludGVyJztcbiAgICBkcmFmdFJvdy5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsIChlKSA9PiB7XG4gICAgICAvLyBEb24ndCBuYXZpZ2F0ZSBpZiBjbGlja2luZyBvbiBjaGVja2JveFxuICAgICAgaWYgKChlLnRhcmdldCBhcyBIVE1MRWxlbWVudCkuY2xvc2VzdCgnaW5wdXRbdHlwZT1cImNoZWNrYm94XCJdJykpIHJldHVybjtcblxuICAgICAgdGhpcy5zd2l0Y2hUb1RhYignYWZzdGVtbmluZycpO1xuICAgIH0pO1xuICB9XG59XG4iLCAiLyoqXG4gKiBFbXBsb3llZXMgQ29udHJvbGxlclxuICpcbiAqIEhhbmRsZXMgY29udGVudCBzd2FwIGJldHdlZW4gbGlzdCB2aWV3IGFuZCBkZXRhaWwgdmlldyxcbiAqIHBsdXMgdGFiIHN3aXRjaGluZyB3aXRoaW4gZWFjaCB2aWV3LlxuICogVXNlcyBIaXN0b3J5IEFQSSBmb3IgYnJvd3NlciBiYWNrL2ZvcndhcmQgbmF2aWdhdGlvbi5cbiAqL1xuXG5leHBvcnQgY2xhc3MgRW1wbG95ZWVzQ29udHJvbGxlciB7XG4gIHByaXZhdGUgcmF0ZXNTeW5jOiBSYXRlc1N5bmNDb250cm9sbGVyIHwgbnVsbCA9IG51bGw7XG4gIHByaXZhdGUgbGlzdFZpZXc6IEhUTUxFbGVtZW50IHwgbnVsbCA9IG51bGw7XG4gIHByaXZhdGUgZGV0YWlsVmlldzogSFRNTEVsZW1lbnQgfCBudWxsID0gbnVsbDtcblxuICBjb25zdHJ1Y3RvcigpIHtcbiAgICB0aGlzLmxpc3RWaWV3ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2VtcGxveWVlcy1saXN0LXZpZXcnKTtcbiAgICB0aGlzLmRldGFpbFZpZXcgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnZW1wbG95ZWUtZGV0YWlsLXZpZXcnKTtcblxuICAgIC8vIE9ubHkgaW5pdGlhbGl6ZSBpZiB3ZSdyZSBvbiB0aGUgZW1wbG95ZWVzIHBhZ2VcbiAgICBpZiAoIXRoaXMubGlzdFZpZXcpIHJldHVybjtcblxuICAgIHRoaXMuc2V0dXBMaXN0VGFicygpO1xuICAgIHRoaXMuc2V0dXBEZXRhaWxUYWJzKCk7XG4gICAgdGhpcy5zZXR1cENoZXZyb25OYXZpZ2F0aW9uKCk7XG4gICAgdGhpcy5zZXR1cEJhY2tOYXZpZ2F0aW9uKCk7XG4gICAgdGhpcy5zZXR1cEhpc3RvcnlOYXZpZ2F0aW9uKCk7XG4gICAgdGhpcy5yZXN0b3JlU3RhdGVGcm9tVXJsKCk7XG4gICAgdGhpcy5yYXRlc1N5bmMgPSBuZXcgUmF0ZXNTeW5jQ29udHJvbGxlcigpO1xuICB9XG5cbiAgLyoqXG4gICAqIFNldHVwIHBvcHN0YXRlIGxpc3RlbmVyIGZvciBicm93c2VyIGJhY2svZm9yd2FyZFxuICAgKi9cbiAgcHJpdmF0ZSBzZXR1cEhpc3RvcnlOYXZpZ2F0aW9uKCk6IHZvaWQge1xuICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdwb3BzdGF0ZScsIChlOiBQb3BTdGF0ZUV2ZW50KSA9PiB7XG4gICAgICBpZiAoZS5zdGF0ZT8uZW1wbG95ZWVLZXkpIHtcbiAgICAgICAgdGhpcy5zaG93RGV0YWlsVmlld0ludGVybmFsKGUuc3RhdGUuZW1wbG95ZWVLZXkpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5zaG93TGlzdFZpZXdJbnRlcm5hbCgpO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlc3RvcmUgdmlldyBzdGF0ZSBmcm9tIFVSTCBvbiBwYWdlIGxvYWRcbiAgICovXG4gIHByaXZhdGUgcmVzdG9yZVN0YXRlRnJvbVVybCgpOiB2b2lkIHtcbiAgICBjb25zdCBoYXNoID0gd2luZG93LmxvY2F0aW9uLmhhc2g7XG4gICAgaWYgKGhhc2guc3RhcnRzV2l0aCgnI2VtcGxveWVlLScpKSB7XG4gICAgICBjb25zdCBlbXBsb3llZUtleSA9IGhhc2guc3Vic3RyaW5nKDEpOyAvLyBSZW1vdmUgI1xuICAgICAgdGhpcy5zaG93RGV0YWlsVmlld0ludGVybmFsKGVtcGxveWVlS2V5KTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogU2V0dXAgdGFiIHN3aXRjaGluZyBmb3IgdGhlIGxpc3Qgdmlld1xuICAgKi9cbiAgcHJpdmF0ZSBzZXR1cExpc3RUYWJzKCk6IHZvaWQge1xuICAgIGlmICghdGhpcy5saXN0VmlldykgcmV0dXJuO1xuXG4gICAgY29uc3QgdGFicyA9IHRoaXMubGlzdFZpZXcucXVlcnlTZWxlY3RvckFsbDxIVE1MRWxlbWVudD4oJ3N3cC10YWItYmFyID4gc3dwLXRhYltkYXRhLXRhYl0nKTtcblxuICAgIHRhYnMuZm9yRWFjaCh0YWIgPT4ge1xuICAgICAgdGFiLmFkZEV2ZW50TGlzdGVuZXIoJ2NsaWNrJywgKCkgPT4ge1xuICAgICAgICBjb25zdCB0YXJnZXRUYWIgPSB0YWIuZGF0YXNldC50YWI7XG4gICAgICAgIGlmICh0YXJnZXRUYWIpIHtcbiAgICAgICAgICB0aGlzLnN3aXRjaFRhYih0aGlzLmxpc3RWaWV3ISwgdGFyZ2V0VGFiKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogU2V0dXAgdGFiIHN3aXRjaGluZyBmb3IgdGhlIGRldGFpbCB2aWV3XG4gICAqL1xuICBwcml2YXRlIHNldHVwRGV0YWlsVGFicygpOiB2b2lkIHtcbiAgICBpZiAoIXRoaXMuZGV0YWlsVmlldykgcmV0dXJuO1xuXG4gICAgY29uc3QgdGFicyA9IHRoaXMuZGV0YWlsVmlldy5xdWVyeVNlbGVjdG9yQWxsPEhUTUxFbGVtZW50Pignc3dwLXRhYi1iYXIgPiBzd3AtdGFiW2RhdGEtdGFiXScpO1xuXG4gICAgdGFicy5mb3JFYWNoKHRhYiA9PiB7XG4gICAgICB0YWIuYWRkRXZlbnRMaXN0ZW5lcignY2xpY2snLCAoKSA9PiB7XG4gICAgICAgIGNvbnN0IHRhcmdldFRhYiA9IHRhYi5kYXRhc2V0LnRhYjtcbiAgICAgICAgaWYgKHRhcmdldFRhYikge1xuICAgICAgICAgIHRoaXMuc3dpdGNoVGFiKHRoaXMuZGV0YWlsVmlldyEsIHRhcmdldFRhYik7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFN3aXRjaCB0byBhIHNwZWNpZmljIHRhYiB3aXRoaW4gYSBjb250YWluZXJcbiAgICovXG4gIHByaXZhdGUgc3dpdGNoVGFiKGNvbnRhaW5lcjogSFRNTEVsZW1lbnQsIHRhcmdldFRhYjogc3RyaW5nKTogdm9pZCB7XG4gICAgY29uc3QgdGFicyA9IGNvbnRhaW5lci5xdWVyeVNlbGVjdG9yQWxsPEhUTUxFbGVtZW50Pignc3dwLXRhYi1iYXIgPiBzd3AtdGFiW2RhdGEtdGFiXScpO1xuICAgIGNvbnN0IGNvbnRlbnRzID0gY29udGFpbmVyLnF1ZXJ5U2VsZWN0b3JBbGw8SFRNTEVsZW1lbnQ+KCdzd3AtdGFiLWNvbnRlbnRbZGF0YS10YWJdJyk7XG5cbiAgICB0YWJzLmZvckVhY2godCA9PiB7XG4gICAgICB0LmNsYXNzTGlzdC50b2dnbGUoJ2FjdGl2ZScsIHQuZGF0YXNldC50YWIgPT09IHRhcmdldFRhYik7XG4gICAgfSk7XG5cbiAgICBjb250ZW50cy5mb3JFYWNoKGNvbnRlbnQgPT4ge1xuICAgICAgY29udGVudC5jbGFzc0xpc3QudG9nZ2xlKCdhY3RpdmUnLCBjb250ZW50LmRhdGFzZXQudGFiID09PSB0YXJnZXRUYWIpO1xuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFNldHVwIHJvdyBjbGljayB0byBzaG93IGRldGFpbCB2aWV3XG4gICAqIElnbm9yZXMgY2xpY2tzIG9uIGFjdGlvbiBidXR0b25zXG4gICAqL1xuICBwcml2YXRlIHNldHVwQ2hldnJvbk5hdmlnYXRpb24oKTogdm9pZCB7XG4gICAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignY2xpY2snLCAoZTogRXZlbnQpID0+IHtcbiAgICAgIGNvbnN0IHRhcmdldCA9IGUudGFyZ2V0IGFzIEhUTUxFbGVtZW50O1xuXG4gICAgICAvLyBJZ25vcmUgY2xpY2tzIG9uIGFjdGlvbiBidXR0b25zXG4gICAgICBpZiAodGFyZ2V0LmNsb3Nlc3QoJ3N3cC1pY29uLWJ0bicpIHx8IHRhcmdldC5jbG9zZXN0KCdzd3AtdGFibGUtYWN0aW9ucycpKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgY29uc3Qgcm93ID0gdGFyZ2V0LmNsb3Nlc3Q8SFRNTEVsZW1lbnQ+KCdzd3AtZGF0YS10YWJsZS1yb3dbZGF0YS1lbXBsb3llZS1kZXRhaWxdJyk7XG5cbiAgICAgIGlmIChyb3cpIHtcbiAgICAgICAgY29uc3QgZW1wbG95ZWVLZXkgPSByb3cuZGF0YXNldC5lbXBsb3llZURldGFpbDtcbiAgICAgICAgaWYgKGVtcGxveWVlS2V5KSB7XG4gICAgICAgICAgdGhpcy5zaG93RGV0YWlsVmlldyhlbXBsb3llZUtleSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTZXR1cCBiYWNrIGJ1dHRvbiB0byByZXR1cm4gdG8gbGlzdCB2aWV3XG4gICAqL1xuICBwcml2YXRlIHNldHVwQmFja05hdmlnYXRpb24oKTogdm9pZCB7XG4gICAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignY2xpY2snLCAoZTogRXZlbnQpID0+IHtcbiAgICAgIGNvbnN0IHRhcmdldCA9IGUudGFyZ2V0IGFzIEhUTUxFbGVtZW50O1xuICAgICAgY29uc3QgYmFja0xpbmsgPSB0YXJnZXQuY2xvc2VzdDxIVE1MRWxlbWVudD4oJ1tkYXRhLWVtcGxveWVlLWJhY2tdJyk7XG5cbiAgICAgIGlmIChiYWNrTGluaykge1xuICAgICAgICB0aGlzLnNob3dMaXN0VmlldygpO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFNob3cgdGhlIGRldGFpbCB2aWV3IGFuZCBoaWRlIGxpc3QgdmlldyAod2l0aCBoaXN0b3J5IHB1c2gpXG4gICAqL1xuICBwcml2YXRlIHNob3dEZXRhaWxWaWV3KGVtcGxveWVlS2V5OiBzdHJpbmcpOiB2b2lkIHtcbiAgICAvLyBQdXNoIHN0YXRlIHRvIGhpc3RvcnlcbiAgICBoaXN0b3J5LnB1c2hTdGF0ZShcbiAgICAgIHsgZW1wbG95ZWVLZXkgfSxcbiAgICAgICcnLFxuICAgICAgYCMke2VtcGxveWVlS2V5fWBcbiAgICApO1xuICAgIHRoaXMuc2hvd0RldGFpbFZpZXdJbnRlcm5hbChlbXBsb3llZUtleSk7XG4gIH1cblxuICAvKipcbiAgICogU2hvdyBkZXRhaWwgdmlldyB3aXRob3V0IG1vZGlmeWluZyBoaXN0b3J5IChmb3IgcG9wc3RhdGUpXG4gICAqL1xuICBwcml2YXRlIHNob3dEZXRhaWxWaWV3SW50ZXJuYWwoZW1wbG95ZWVLZXk6IHN0cmluZyk6IHZvaWQge1xuICAgIGlmICh0aGlzLmxpc3RWaWV3ICYmIHRoaXMuZGV0YWlsVmlldykge1xuICAgICAgdGhpcy5saXN0Vmlldy5zdHlsZS5kaXNwbGF5ID0gJ25vbmUnO1xuICAgICAgdGhpcy5kZXRhaWxWaWV3LnN0eWxlLmRpc3BsYXkgPSAnYmxvY2snO1xuICAgICAgdGhpcy5kZXRhaWxWaWV3LmRhdGFzZXQuZW1wbG95ZWUgPSBlbXBsb3llZUtleTtcblxuICAgICAgLy8gUmVzZXQgdG8gZmlyc3QgdGFiXG4gICAgICB0aGlzLnN3aXRjaFRhYih0aGlzLmRldGFpbFZpZXcsICdnZW5lcmFsJyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFNob3cgdGhlIGxpc3QgdmlldyBhbmQgaGlkZSBkZXRhaWwgdmlldyAod2l0aCBoaXN0b3J5IHB1c2gpXG4gICAqL1xuICBwcml2YXRlIHNob3dMaXN0VmlldygpOiB2b2lkIHtcbiAgICAvLyBQdXNoIHN0YXRlIHRvIGhpc3RvcnkgKGNsZWFyIGhhc2gpXG4gICAgaGlzdG9yeS5wdXNoU3RhdGUoXG4gICAgICB7fSxcbiAgICAgICcnLFxuICAgICAgd2luZG93LmxvY2F0aW9uLnBhdGhuYW1lXG4gICAgKTtcbiAgICB0aGlzLnNob3dMaXN0Vmlld0ludGVybmFsKCk7XG4gIH1cblxuICAvKipcbiAgICogU2hvdyBsaXN0IHZpZXcgd2l0aG91dCBtb2RpZnlpbmcgaGlzdG9yeSAoZm9yIHBvcHN0YXRlKVxuICAgKi9cbiAgcHJpdmF0ZSBzaG93TGlzdFZpZXdJbnRlcm5hbCgpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5saXN0VmlldyAmJiB0aGlzLmRldGFpbFZpZXcpIHtcbiAgICAgIHRoaXMuZGV0YWlsVmlldy5zdHlsZS5kaXNwbGF5ID0gJ25vbmUnO1xuICAgICAgdGhpcy5saXN0Vmlldy5zdHlsZS5kaXNwbGF5ID0gJ2Jsb2NrJztcbiAgICB9XG4gIH1cbn1cblxuLyoqXG4gKiBSYXRlcyBTeW5jIENvbnRyb2xsZXJcbiAqXG4gKiBTeW5jcyBjaGFuZ2VzIGJldHdlZW4gdGhlIHJhdGVzIGRyYXdlciBhbmQgdGhlIHNhbGFyeSB0YWIgY2FyZHMuXG4gKiBVc2VzIElELWJhc2VkIGxvb2t1cHM6XG4gKiAtIENoZWNrYm94OiBpZD1cInJhdGUte2tleX0tZW5hYmxlZFwiXG4gKiAtIFRleHQgaW5wdXQ6IGlkPVwicmF0ZS17a2V5fVwiXG4gKiAtIENhcmQgcm93OiBpZD1cImNhcmQte2tleX1cIlxuICovXG5jbGFzcyBSYXRlc1N5bmNDb250cm9sbGVyIHtcbiAgcHJpdmF0ZSBkcmF3ZXI6IEhUTUxFbGVtZW50IHwgbnVsbCA9IG51bGw7XG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgdGhpcy5kcmF3ZXIgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgncmF0ZXMtZHJhd2VyJyk7XG5cbiAgICBpZiAoIXRoaXMuZHJhd2VyKSByZXR1cm47XG5cbiAgICB0aGlzLnNldHVwQ2hlY2tib3hMaXN0ZW5lcnMoKTtcbiAgICB0aGlzLnNldHVwSW5wdXRMaXN0ZW5lcnMoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBFeHRyYWN0IHJhdGUga2V5IGZyb20gY2hlY2tib3ggSUQgKGUuZy4sIFwicmF0ZS1ub3JtYWwtZW5hYmxlZFwiIFx1MjE5MiBcIm5vcm1hbFwiKVxuICAgKi9cbiAgcHJpdmF0ZSBleHRyYWN0UmF0ZUtleShjaGVja2JveElkOiBzdHJpbmcpOiBzdHJpbmcgfCBudWxsIHtcbiAgICBjb25zdCBtYXRjaCA9IGNoZWNrYm94SWQubWF0Y2goL15yYXRlLSguKyktZW5hYmxlZCQvKTtcbiAgICByZXR1cm4gbWF0Y2ggPyBtYXRjaFsxXSA6IG51bGw7XG4gIH1cblxuICAvKipcbiAgICogU2V0dXAgY2hlY2tib3ggY2hhbmdlIGxpc3RlbmVycyBpbiBkcmF3ZXJcbiAgICovXG4gIHByaXZhdGUgc2V0dXBDaGVja2JveExpc3RlbmVycygpOiB2b2lkIHtcbiAgICBpZiAoIXRoaXMuZHJhd2VyKSByZXR1cm47XG5cbiAgICB0aGlzLmRyYXdlci5hZGRFdmVudExpc3RlbmVyKCdjaGFuZ2UnLCAoZTogRXZlbnQpID0+IHtcbiAgICAgIGNvbnN0IHRhcmdldCA9IGUudGFyZ2V0IGFzIEhUTUxJbnB1dEVsZW1lbnQ7XG4gICAgICBpZiAodGFyZ2V0LnR5cGUgIT09ICdjaGVja2JveCcgfHwgIXRhcmdldC5pZCkgcmV0dXJuO1xuXG4gICAgICBjb25zdCByYXRlS2V5ID0gdGhpcy5leHRyYWN0UmF0ZUtleSh0YXJnZXQuaWQpO1xuICAgICAgaWYgKCFyYXRlS2V5KSByZXR1cm47XG5cbiAgICAgIGNvbnN0IGlzQ2hlY2tlZCA9IHRhcmdldC5jaGVja2VkO1xuICAgICAgY29uc3Qgcm93ID0gdGFyZ2V0LmNsb3Nlc3Q8SFRNTEVsZW1lbnQ+KCdzd3AtZGF0YS1yb3cnKTtcbiAgICAgIGlmICghcm93KSByZXR1cm47XG5cbiAgICAgIC8vIFRvZ2dsZSBkaXNhYmxlZCBjbGFzcyBpbiBkcmF3ZXIgcm93XG4gICAgICBjb25zdCBsYWJlbCA9IHJvdy5xdWVyeVNlbGVjdG9yKCdzd3AtZGF0YS1sYWJlbCcpO1xuICAgICAgY29uc3QgaW5wdXQgPSByb3cucXVlcnlTZWxlY3Rvcignc3dwLWRhdGEtaW5wdXQnKTtcbiAgICAgIGlmIChsYWJlbCkgbGFiZWwuY2xhc3NMaXN0LnRvZ2dsZSgnZGlzYWJsZWQnLCAhaXNDaGVja2VkKTtcbiAgICAgIGlmIChpbnB1dCkgaW5wdXQuY2xhc3NMaXN0LnRvZ2dsZSgnZGlzYWJsZWQnLCAhaXNDaGVja2VkKTtcblxuICAgICAgLy8gVG9nZ2xlIHZpc2liaWxpdHkgaW4gY2FyZFxuICAgICAgdGhpcy50b2dnbGVDYXJkUm93KHJhdGVLZXksIGlzQ2hlY2tlZCk7XG5cbiAgICAgIC8vIElmIGVuYWJsaW5nLCBhbHNvIHN5bmMgdGhlIGN1cnJlbnQgdmFsdWVcbiAgICAgIGlmIChpc0NoZWNrZWQpIHtcbiAgICAgICAgY29uc3QgdGV4dElucHV0ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoYHJhdGUtJHtyYXRlS2V5fWApIGFzIEhUTUxJbnB1dEVsZW1lbnQgfCBudWxsO1xuICAgICAgICBpZiAodGV4dElucHV0KSB7XG4gICAgICAgICAgdGhpcy5zeW5jVmFsdWVUb0NhcmQocmF0ZUtleSwgdGV4dElucHV0LnZhbHVlKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFNldHVwIGlucHV0IGNoYW5nZSBsaXN0ZW5lcnMgaW4gZHJhd2VyXG4gICAqL1xuICBwcml2YXRlIHNldHVwSW5wdXRMaXN0ZW5lcnMoKTogdm9pZCB7XG4gICAgaWYgKCF0aGlzLmRyYXdlcikgcmV0dXJuO1xuXG4gICAgdGhpcy5kcmF3ZXIuYWRkRXZlbnRMaXN0ZW5lcignaW5wdXQnLCAoZTogRXZlbnQpID0+IHtcbiAgICAgIGNvbnN0IHRhcmdldCA9IGUudGFyZ2V0IGFzIEhUTUxJbnB1dEVsZW1lbnQ7XG4gICAgICBpZiAodGFyZ2V0LnR5cGUgIT09ICd0ZXh0JyB8fCAhdGFyZ2V0LmlkKSByZXR1cm47XG5cbiAgICAgIC8vIEV4dHJhY3QgcmF0ZSBrZXkgZnJvbSBpbnB1dCBJRCAoZS5nLiwgXCJyYXRlLW5vcm1hbFwiIFx1MjE5MiBcIm5vcm1hbFwiKVxuICAgICAgY29uc3QgbWF0Y2ggPSB0YXJnZXQuaWQubWF0Y2goL15yYXRlLSguKykkLyk7XG4gICAgICBpZiAoIW1hdGNoKSByZXR1cm47XG5cbiAgICAgIGNvbnN0IHJhdGVLZXkgPSBtYXRjaFsxXTtcbiAgICAgIC8vIFNraXAgaWYgdGhpcyBtYXRjaGVzIHRoZSBjaGVja2JveCBwYXR0ZXJuXG4gICAgICBpZiAocmF0ZUtleS5lbmRzV2l0aCgnLWVuYWJsZWQnKSkgcmV0dXJuO1xuXG4gICAgICB0aGlzLnN5bmNWYWx1ZVRvQ2FyZChyYXRlS2V5LCB0YXJnZXQudmFsdWUpO1xuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFRvZ2dsZSBjYXJkIHJvdyB2aXNpYmlsaXR5IGJ5IElEXG4gICAqL1xuICBwcml2YXRlIHRvZ2dsZUNhcmRSb3cocmF0ZUtleTogc3RyaW5nLCB2aXNpYmxlOiBib29sZWFuKTogdm9pZCB7XG4gICAgY29uc3QgY2FyZFJvdyA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKGBjYXJkLSR7cmF0ZUtleX1gKTtcbiAgICBpZiAoY2FyZFJvdykge1xuICAgICAgY2FyZFJvdy5zdHlsZS5kaXNwbGF5ID0gdmlzaWJsZSA/ICcnIDogJ25vbmUnO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBGb3JtYXQgbnVtYmVyIHdpdGggMiBkZWNpbWFscyB1c2luZyBEYW5pc2ggbG9jYWxlIChjb21tYSBhcyBkZWNpbWFsIHNlcGFyYXRvcilcbiAgICovXG4gIHByaXZhdGUgZm9ybWF0TnVtYmVyKHZhbHVlOiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIC8vIFBhcnNlIHRoZSBpbnB1dCAoaGFuZGxlIGJvdGggZG90IGFuZCBjb21tYSBhcyBkZWNpbWFsIHNlcGFyYXRvcilcbiAgICBjb25zdCBub3JtYWxpemVkID0gdmFsdWUucmVwbGFjZSgnLCcsICcuJyk7XG4gICAgY29uc3QgbnVtID0gcGFyc2VGbG9hdChub3JtYWxpemVkKTtcblxuICAgIGlmIChpc05hTihudW0pKSByZXR1cm4gdmFsdWU7XG5cbiAgICAvLyBGb3JtYXQgd2l0aCAyIGRlY2ltYWxzIGFuZCBjb21tYSBhcyBkZWNpbWFsIHNlcGFyYXRvclxuICAgIHJldHVybiBudW0udG9GaXhlZCgyKS5yZXBsYWNlKCcuJywgJywnKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTeW5jIHZhbHVlIGZyb20gZHJhd2VyIHRvIGNhcmQgYnkgSURcbiAgICovXG4gIHByaXZhdGUgc3luY1ZhbHVlVG9DYXJkKHJhdGVLZXk6IHN0cmluZywgdmFsdWU6IHN0cmluZyk6IHZvaWQge1xuICAgIGNvbnN0IGNhcmRJbnB1dCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKGB2YWx1ZS0ke3JhdGVLZXl9YCkgYXMgSFRNTElucHV0RWxlbWVudCB8IG51bGw7XG4gICAgaWYgKCFjYXJkSW5wdXQpIHJldHVybjtcblxuICAgIC8vIEdldCB0aGUgdW5pdCBmcm9tIGRyYXdlciBpbnB1dCBjb250YWluZXJcbiAgICBjb25zdCB0ZXh0SW5wdXQgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZChgcmF0ZS0ke3JhdGVLZXl9YCk7XG4gICAgY29uc3QgaW5wdXRDb250YWluZXIgPSB0ZXh0SW5wdXQ/LmNsb3Nlc3QoJ3N3cC1kYXRhLWlucHV0Jyk7XG4gICAgY29uc3QgdW5pdCA9IGlucHV0Q29udGFpbmVyPy50ZXh0Q29udGVudD8udHJpbSgpLnJlcGxhY2UodmFsdWUsICcnKS50cmltKCkgfHwgJ2tyJztcblxuICAgIC8vIEZvcm1hdCB3aXRoIDIgZGVjaW1hbHNcbiAgICBjb25zdCBmb3JtYXR0ZWRWYWx1ZSA9IHRoaXMuZm9ybWF0TnVtYmVyKHZhbHVlKTtcbiAgICBjYXJkSW5wdXQudmFsdWUgPSBgJHtmb3JtYXR0ZWRWYWx1ZX0gJHt1bml0fWA7XG4gIH1cbn1cbiIsICIvKipcbiAqIFNhbG9uIE9TIEFwcFxuICpcbiAqIE1haW4gYXBwbGljYXRpb24gY2xhc3MgdGhhdCBvcmNoZXN0cmF0ZXMgYWxsIFVJIGNvbnRyb2xsZXJzXG4gKi9cblxuaW1wb3J0IHsgU2lkZWJhckNvbnRyb2xsZXIgfSBmcm9tICcuL21vZHVsZXMvc2lkZWJhcic7XG5pbXBvcnQgeyBEcmF3ZXJDb250cm9sbGVyIH0gZnJvbSAnLi9tb2R1bGVzL2RyYXdlcnMnO1xuaW1wb3J0IHsgVGhlbWVDb250cm9sbGVyIH0gZnJvbSAnLi9tb2R1bGVzL3RoZW1lJztcbmltcG9ydCB7IFNlYXJjaENvbnRyb2xsZXIgfSBmcm9tICcuL21vZHVsZXMvc2VhcmNoJztcbmltcG9ydCB7IExvY2tTY3JlZW5Db250cm9sbGVyIH0gZnJvbSAnLi9tb2R1bGVzL2xvY2tzY3JlZW4nO1xuaW1wb3J0IHsgQ2FzaENvbnRyb2xsZXIgfSBmcm9tICcuL21vZHVsZXMvY2FzaCc7XG5pbXBvcnQgeyBFbXBsb3llZXNDb250cm9sbGVyIH0gZnJvbSAnLi9tb2R1bGVzL2VtcGxveWVlcyc7XG5cbi8qKlxuICogTWFpbiBhcHBsaWNhdGlvbiBjbGFzc1xuICovXG5leHBvcnQgY2xhc3MgQXBwIHtcbiAgcmVhZG9ubHkgc2lkZWJhcjogU2lkZWJhckNvbnRyb2xsZXI7XG4gIHJlYWRvbmx5IGRyYXdlcnM6IERyYXdlckNvbnRyb2xsZXI7XG4gIHJlYWRvbmx5IHRoZW1lOiBUaGVtZUNvbnRyb2xsZXI7XG4gIHJlYWRvbmx5IHNlYXJjaDogU2VhcmNoQ29udHJvbGxlcjtcbiAgcmVhZG9ubHkgbG9ja1NjcmVlbjogTG9ja1NjcmVlbkNvbnRyb2xsZXI7XG4gIHJlYWRvbmx5IGNhc2g6IENhc2hDb250cm9sbGVyO1xuICByZWFkb25seSBlbXBsb3llZXM6IEVtcGxveWVlc0NvbnRyb2xsZXI7XG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgLy8gSW5pdGlhbGl6ZSBjb250cm9sbGVyc1xuICAgIHRoaXMuc2lkZWJhciA9IG5ldyBTaWRlYmFyQ29udHJvbGxlcigpO1xuICAgIHRoaXMuZHJhd2VycyA9IG5ldyBEcmF3ZXJDb250cm9sbGVyKCk7XG4gICAgdGhpcy50aGVtZSA9IG5ldyBUaGVtZUNvbnRyb2xsZXIoKTtcbiAgICB0aGlzLnNlYXJjaCA9IG5ldyBTZWFyY2hDb250cm9sbGVyKCk7XG4gICAgdGhpcy5sb2NrU2NyZWVuID0gbmV3IExvY2tTY3JlZW5Db250cm9sbGVyKHRoaXMuZHJhd2Vycyk7XG4gICAgdGhpcy5jYXNoID0gbmV3IENhc2hDb250cm9sbGVyKCk7XG4gICAgdGhpcy5lbXBsb3llZXMgPSBuZXcgRW1wbG95ZWVzQ29udHJvbGxlcigpO1xuICB9XG59XG5cbi8qKlxuICogR2xvYmFsIGFwcCBpbnN0YW5jZVxuICovXG5sZXQgYXBwOiBBcHA7XG5cbi8qKlxuICogSW5pdGlhbGl6ZSB0aGUgYXBwbGljYXRpb25cbiAqL1xuZnVuY3Rpb24gaW5pdCgpOiB2b2lkIHtcbiAgYXBwID0gbmV3IEFwcCgpO1xuXG4gIC8vIEV4cG9zZSB0byB3aW5kb3cgZm9yIGRlYnVnZ2luZ1xuICBpZiAodHlwZW9mIHdpbmRvdyAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAod2luZG93IGFzIHVua25vd24gYXMgeyBhcHA6IEFwcCB9KS5hcHAgPSBhcHA7XG4gIH1cbn1cblxuLy8gV2FpdCBmb3IgRE9NIHJlYWR5XG5pZiAoZG9jdW1lbnQucmVhZHlTdGF0ZSA9PT0gJ2xvYWRpbmcnKSB7XG4gIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ0RPTUNvbnRlbnRMb2FkZWQnLCBpbml0KTtcbn0gZWxzZSB7XG4gIGluaXQoKTtcbn1cblxuZXhwb3J0IHsgYXBwIH07XG5leHBvcnQgZGVmYXVsdCBBcHA7XG4iXSwKICAibWFwcGluZ3MiOiAiOzs7O0FBTU8sSUFBTSxxQkFBTixNQUFNLG1CQUFrQjtBQUFBLEVBSzdCLGNBQWM7QUFKZCxTQUFRLGFBQWlDO0FBQ3pDLFNBQVEsWUFBZ0M7QUFDeEMsU0FBUSxjQUFrQztBQUd4QyxTQUFLLGFBQWEsU0FBUyxlQUFlLFlBQVk7QUFDdEQsU0FBSyxZQUFZLFNBQVMsY0FBYyxnQkFBZ0I7QUFDeEQsU0FBSyxjQUFjLFNBQVMsZUFBZSxhQUFhO0FBRXhELFNBQUssZUFBZTtBQUNwQixTQUFLLGNBQWM7QUFDbkIsU0FBSyxhQUFhO0FBQUEsRUFDcEI7QUFBQTtBQUFBO0FBQUE7QUFBQSxFQUtBLElBQUksY0FBdUI7QUFDekIsV0FBTyxLQUFLLFdBQVcsVUFBVSxTQUFTLGdCQUFnQixLQUFLO0FBQUEsRUFDakU7QUFBQTtBQUFBO0FBQUE7QUFBQSxFQUtBLFNBQWU7QUFDYixRQUFJLENBQUMs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 diff --git a/PlanTempus.Application/wwwroot/ts/modules/employees.ts b/PlanTempus.Application/wwwroot/ts/modules/employees.ts index d400efd..7c575c2 100644 --- a/PlanTempus.Application/wwwroot/ts/modules/employees.ts +++ b/PlanTempus.Application/wwwroot/ts/modules/employees.ts @@ -116,7 +116,7 @@ export class EmployeesController { return; } - const row = target.closest('swp-employee-row[data-employee-detail]'); + const row = target.closest('swp-data-table-row[data-employee-detail]'); if (row) { const employeeKey = row.dataset.employeeDetail;