valtech-components 2.0.404 → 2.0.407
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +71 -0
- package/esm2022/lib/components/atoms/avatar/avatar.component.mjs +4 -4
- package/esm2022/lib/components/atoms/avatar/types.mjs +1 -1
- package/esm2022/lib/components/atoms/box/box.component.mjs +4 -4
- package/esm2022/lib/components/atoms/box/types.mjs +1 -1
- package/esm2022/lib/components/atoms/button/button.component.mjs +6 -6
- package/esm2022/lib/components/atoms/button/factory.mjs +1 -1
- package/esm2022/lib/components/atoms/countdown/countdown.component.mjs +343 -0
- package/esm2022/lib/components/atoms/countdown/types.mjs +27 -0
- package/esm2022/lib/components/atoms/display/display.component.mjs +4 -4
- package/esm2022/lib/components/atoms/display/types.mjs +1 -1
- package/esm2022/lib/components/atoms/divider/divider.component.mjs +4 -4
- package/esm2022/lib/components/atoms/divider/types.mjs +1 -1
- package/esm2022/lib/components/atoms/fab/fab.component.mjs +152 -0
- package/esm2022/lib/components/atoms/fab/types.mjs +2 -0
- package/esm2022/lib/components/atoms/href/href.component.mjs +4 -4
- package/esm2022/lib/components/atoms/href/types.mjs +1 -1
- package/esm2022/lib/components/atoms/icon/icon.component.mjs +4 -4
- package/esm2022/lib/components/atoms/icon/types.mjs +1 -1
- package/esm2022/lib/components/atoms/image/image.component.mjs +6 -6
- package/esm2022/lib/components/atoms/image/types.mjs +1 -1
- package/esm2022/lib/components/atoms/price-tag/price-tag.component.mjs +245 -0
- package/esm2022/lib/components/atoms/price-tag/types.mjs +15 -0
- package/esm2022/lib/components/atoms/progress-bar/progress-bar.component.mjs +4 -4
- package/esm2022/lib/components/atoms/progress-bar/types.mjs +1 -1
- package/esm2022/lib/components/atoms/progress-ring/progress-ring.component.mjs +149 -0
- package/esm2022/lib/components/atoms/progress-ring/types.mjs +2 -0
- package/esm2022/lib/components/atoms/qr-code/qr-code.component.mjs +417 -0
- package/esm2022/lib/components/atoms/qr-code/types.mjs +2 -0
- package/esm2022/lib/components/atoms/skeleton/skeleton.component.mjs +193 -0
- package/esm2022/lib/components/atoms/skeleton/types.mjs +13 -0
- package/esm2022/lib/components/atoms/text/text.component.mjs +4 -4
- package/esm2022/lib/components/atoms/text/types.mjs +1 -1
- package/esm2022/lib/components/atoms/title/title.component.mjs +4 -4
- package/esm2022/lib/components/atoms/title/types.mjs +1 -1
- package/esm2022/lib/components/molecules/accordion/accordion.component.mjs +139 -0
- package/esm2022/lib/components/molecules/accordion/types.mjs +2 -0
- package/esm2022/lib/components/molecules/action-header/action-header.component.mjs +4 -4
- package/esm2022/lib/components/molecules/action-header/types.mjs +1 -1
- package/esm2022/lib/components/molecules/alert-box/alert-box.component.mjs +4 -4
- package/esm2022/lib/components/molecules/alert-box/types.mjs +1 -1
- package/esm2022/lib/components/molecules/breadcrumb/breadcrumb.component.mjs +137 -0
- package/esm2022/lib/components/molecules/breadcrumb/types.mjs +2 -0
- package/esm2022/lib/components/molecules/button-group/button-group.component.mjs +4 -4
- package/esm2022/lib/components/molecules/button-group/types.mjs +1 -1
- package/esm2022/lib/components/molecules/card/card.component.mjs +5 -5
- package/esm2022/lib/components/molecules/card/types.mjs +1 -1
- package/esm2022/lib/components/molecules/check-input/check-input.component.mjs +4 -4
- package/esm2022/lib/components/molecules/chip-group/chip-group.component.mjs +174 -0
- package/esm2022/lib/components/molecules/chip-group/types.mjs +2 -0
- package/esm2022/lib/components/molecules/code-display/code-display.component.mjs +4 -4
- package/esm2022/lib/components/molecules/code-display/types.mjs +1 -1
- package/esm2022/lib/components/molecules/command-display/command-display.component.mjs +4 -4
- package/esm2022/lib/components/molecules/command-display/types.mjs +1 -1
- package/esm2022/lib/components/molecules/comment/comment.component.mjs +634 -0
- package/esm2022/lib/components/molecules/comment/types.mjs +2 -0
- package/esm2022/lib/components/molecules/comment-input/comment-input.component.mjs +4 -4
- package/esm2022/lib/components/molecules/content-loader/content-loader.component.mjs +4 -4
- package/esm2022/lib/components/molecules/content-loader/types.mjs +1 -1
- package/esm2022/lib/components/molecules/currency-input/currency-input.component.mjs +368 -0
- package/esm2022/lib/components/molecules/currency-input/types.mjs +18 -0
- package/esm2022/lib/components/molecules/date-input/date-input.component.mjs +5 -5
- package/esm2022/lib/components/molecules/date-range-input/date-range-input.component.mjs +418 -0
- package/esm2022/lib/components/molecules/date-range-input/types.mjs +2 -0
- package/esm2022/lib/components/molecules/email-input/email-input.component.mjs +4 -4
- package/esm2022/lib/components/molecules/expandable-text/expandable-text.component.mjs +4 -4
- package/esm2022/lib/components/molecules/expandable-text/types.mjs +1 -1
- package/esm2022/lib/components/molecules/file-input/file-input.component.mjs +4 -4
- package/esm2022/lib/components/molecules/glow-card/glow-card.component.mjs +279 -0
- package/esm2022/lib/components/molecules/glow-card/types.mjs +11 -0
- package/esm2022/lib/components/molecules/hint/hint.component.mjs +4 -4
- package/esm2022/lib/components/molecules/hour-input/hour-input.component.mjs +4 -4
- package/esm2022/lib/components/molecules/info/info.component.mjs +4 -4
- package/esm2022/lib/components/molecules/info/types.mjs +1 -1
- package/esm2022/lib/components/molecules/language-selector/language-selector.component.mjs +4 -4
- package/esm2022/lib/components/molecules/language-selector/types.mjs +1 -1
- package/esm2022/lib/components/molecules/layered-card/layered-card.component.mjs +4 -4
- package/esm2022/lib/components/molecules/layered-card/types.mjs +1 -1
- package/esm2022/lib/components/molecules/link/link.component.mjs +4 -4
- package/esm2022/lib/components/molecules/link/types.mjs +1 -1
- package/esm2022/lib/components/molecules/links-cake/links-cake.component.mjs +4 -4
- package/esm2022/lib/components/molecules/links-cake/types.mjs +1 -1
- package/esm2022/lib/components/molecules/multi-select-search/multi-select-search.component.mjs +5 -5
- package/esm2022/lib/components/molecules/notes-box/notes-box.component.mjs +4 -4
- package/esm2022/lib/components/molecules/notes-box/types.mjs +1 -1
- package/esm2022/lib/components/molecules/number-from-to/number-from-to.component.mjs +4 -4
- package/esm2022/lib/components/molecules/number-input/number-input.component.mjs +4 -4
- package/esm2022/lib/components/molecules/number-stepper/number-stepper.component.mjs +377 -0
- package/esm2022/lib/components/molecules/number-stepper/types.mjs +2 -0
- package/esm2022/lib/components/molecules/pagination/pagination.component.mjs +253 -0
- package/esm2022/lib/components/molecules/pagination/types.mjs +2 -0
- package/esm2022/lib/components/molecules/participant-card/participant-card.component.mjs +486 -0
- package/esm2022/lib/components/molecules/participant-card/types.mjs +21 -0
- package/esm2022/lib/components/molecules/password-input/password-input.component.mjs +4 -4
- package/esm2022/lib/components/molecules/phone-input/phone-input.component.mjs +336 -0
- package/esm2022/lib/components/molecules/phone-input/types.mjs +19 -0
- package/esm2022/lib/components/molecules/pill/pill.component.mjs +4 -4
- package/esm2022/lib/components/molecules/pill/types.mjs +1 -1
- package/esm2022/lib/components/molecules/pin-input/pin-input.component.mjs +4 -4
- package/esm2022/lib/components/molecules/plain-code-box/plain-code-box.component.mjs +4 -4
- package/esm2022/lib/components/molecules/plain-code-box/types.mjs +1 -1
- package/esm2022/lib/components/molecules/popover-selector/popover-selector.component.mjs +5 -5
- package/esm2022/lib/components/molecules/popover-selector/types.mjs +1 -1
- package/esm2022/lib/components/molecules/progress-status/progress-status.component.mjs +4 -4
- package/esm2022/lib/components/molecules/progress-status/types.mjs +1 -1
- package/esm2022/lib/components/molecules/prompter/prompter.component.mjs +4 -4
- package/esm2022/lib/components/molecules/prompter/types.mjs +1 -1
- package/esm2022/lib/components/molecules/quote-box/quote-box.component.mjs +155 -0
- package/esm2022/lib/components/molecules/radio-input/radio-input.component.mjs +5 -5
- package/esm2022/lib/components/molecules/raffle-status-card/raffle-status-card.component.mjs +484 -0
- package/esm2022/lib/components/molecules/raffle-status-card/types.mjs +23 -0
- package/esm2022/lib/components/molecules/range-input/range-input.component.mjs +148 -0
- package/esm2022/lib/components/molecules/range-input/types.mjs +2 -0
- package/esm2022/lib/components/molecules/rating/rating.component.mjs +149 -0
- package/esm2022/lib/components/molecules/rating/types.mjs +2 -0
- package/esm2022/lib/components/molecules/searchbar/searchbar.component.mjs +4 -4
- package/esm2022/lib/components/molecules/segment-control/segment-control.component.mjs +145 -0
- package/esm2022/lib/components/molecules/segment-control/types.mjs +2 -0
- package/esm2022/lib/components/molecules/select-input/select-input.component.mjs +5 -5
- package/esm2022/lib/components/molecules/select-search/select-search.component.mjs +5 -5
- package/esm2022/lib/components/molecules/share-buttons/share-buttons.component.mjs +277 -0
- package/esm2022/lib/components/molecules/share-buttons/types.mjs +88 -0
- package/esm2022/lib/components/molecules/stats-card/stats-card.component.mjs +165 -0
- package/esm2022/lib/components/molecules/stats-card/types.mjs +2 -0
- package/esm2022/lib/components/molecules/stepper/stepper.component.mjs +239 -0
- package/esm2022/lib/components/molecules/stepper/types.mjs +2 -0
- package/esm2022/lib/components/molecules/tabs/tabs.component.mjs +135 -0
- package/esm2022/lib/components/molecules/tabs/types.mjs +2 -0
- package/esm2022/lib/components/molecules/text-input/text-input.component.mjs +4 -4
- package/esm2022/lib/components/molecules/textarea-input/textarea-input.component.mjs +204 -0
- package/esm2022/lib/components/molecules/textarea-input/types.mjs +2 -0
- package/esm2022/lib/components/molecules/ticket-grid/ticket-grid.component.mjs +497 -0
- package/esm2022/lib/components/molecules/ticket-grid/types.mjs +11 -0
- package/esm2022/lib/components/molecules/timeline/timeline.component.mjs +140 -0
- package/esm2022/lib/components/molecules/timeline/types.mjs +2 -0
- package/esm2022/lib/components/molecules/title-block/title-block.component.mjs +4 -4
- package/esm2022/lib/components/molecules/title-block/types.mjs +1 -1
- package/esm2022/lib/components/molecules/toggle-input/toggle-input.component.mjs +89 -0
- package/esm2022/lib/components/molecules/toggle-input/types.mjs +2 -0
- package/esm2022/lib/components/molecules/winner-display/types.mjs +9 -0
- package/esm2022/lib/components/molecules/winner-display/winner-display.component.mjs +370 -0
- package/esm2022/lib/components/organisms/article/article.component.mjs +4 -4
- package/esm2022/lib/components/organisms/article/types.mjs +1 -1
- package/esm2022/lib/components/organisms/banner/banner.component.mjs +4 -4
- package/esm2022/lib/components/organisms/banner/types.mjs +1 -1
- package/esm2022/lib/components/organisms/comment-section/comment-section.component.mjs +578 -0
- package/esm2022/lib/components/organisms/comment-section/types.mjs +2 -0
- package/esm2022/lib/components/organisms/data-table/data-table.component.mjs +853 -0
- package/esm2022/lib/components/organisms/data-table/types.mjs +13 -0
- package/esm2022/lib/components/organisms/footer/footer.component.mjs +4 -4
- package/esm2022/lib/components/organisms/footer/types.mjs +1 -1
- package/esm2022/lib/components/organisms/form/factory.mjs +1 -1
- package/esm2022/lib/components/organisms/form/form-footer/form-footer.component.mjs +4 -4
- package/esm2022/lib/components/organisms/form/form.component.mjs +4 -4
- package/esm2022/lib/components/organisms/header/header.component.mjs +4 -4
- package/esm2022/lib/components/organisms/header/types.mjs +1 -1
- package/esm2022/lib/components/organisms/item-list/item-list.component.mjs +4 -4
- package/esm2022/lib/components/organisms/item-list/types.mjs +1 -1
- package/esm2022/lib/components/organisms/no-content/no-content.component.mjs +4 -4
- package/esm2022/lib/components/organisms/no-content/types.mjs +1 -1
- package/esm2022/lib/components/organisms/toolbar/toolbar.component.mjs +4 -4
- package/esm2022/lib/components/organisms/toolbar/types.mjs +1 -1
- package/esm2022/lib/components/organisms/wizard/types.mjs +1 -1
- package/esm2022/lib/components/organisms/wizard/wizard-footer/wizard-footer.component.mjs +4 -4
- package/esm2022/lib/components/organisms/wizard/wizard.component.mjs +4 -4
- package/esm2022/lib/components/templates/layout/layout.component.mjs +4 -4
- package/esm2022/lib/components/templates/simple/simple.component.mjs +5 -5
- package/esm2022/lib/components/templates/simple/types.mjs +1 -1
- package/esm2022/lib/components/types.mjs +22 -16
- package/esm2022/lib/services/confirmation-dialog/confirmation-dialog.service.mjs +180 -0
- package/esm2022/lib/services/confirmation-dialog/types.mjs +14 -0
- package/esm2022/lib/services/download.service.mjs +4 -4
- package/esm2022/lib/services/icons.service.mjs +4 -4
- package/esm2022/lib/services/in-app-browser.service.mjs +4 -4
- package/esm2022/lib/services/lang-provider/components/lang-settings.mjs +1 -1
- package/esm2022/lib/services/lang-provider/content.mjs +1 -1
- package/esm2022/lib/services/lang-provider/lang-provider.service.mjs +4 -4
- package/esm2022/lib/services/lang-provider/types.mjs +1 -1
- package/esm2022/lib/services/link-processor.service.mjs +4 -4
- package/esm2022/lib/services/local-storage.service.mjs +1 -1
- package/esm2022/lib/services/modal/modal.service.mjs +213 -0
- package/esm2022/lib/services/modal/simple-modal-content.component.mjs +133 -0
- package/esm2022/lib/services/modal/types.mjs +26 -0
- package/esm2022/lib/services/navigation.service.mjs +4 -4
- package/esm2022/lib/services/qr-generator/qr-generator.service.mjs +341 -0
- package/esm2022/lib/services/qr-generator/types.mjs +46 -0
- package/esm2022/lib/services/theme.service.mjs +4 -4
- package/esm2022/lib/services/toast.service.mjs +4 -4
- package/esm2022/lib/services/types.mjs +1 -1
- package/esm2022/lib/shared/constants/storage.mjs +1 -1
- package/esm2022/lib/shared/pipes/process-links.pipe.mjs +4 -4
- package/esm2022/lib/shared/utils/content.mjs +1 -1
- package/esm2022/lib/shared/utils/dom.mjs +1 -1
- package/esm2022/lib/shared/utils/form-defaults.mjs +1 -1
- package/esm2022/lib/shared/utils/simple-content.mjs +1 -1
- package/esm2022/lib/shared/utils/styles.mjs +1 -1
- package/esm2022/lib/shared/utils/text.mjs +1 -1
- package/esm2022/public-api.mjs +73 -3
- package/esm2022/valtech-components.mjs +1 -1
- package/fesm2022/valtech-components-simple-modal-content.component-DQhEgUmS.mjs +136 -0
- package/fesm2022/valtech-components-simple-modal-content.component-DQhEgUmS.mjs.map +1 -0
- package/fesm2022/valtech-components.mjs +14848 -4293
- package/fesm2022/valtech-components.mjs.map +1 -1
- package/lib/components/atoms/countdown/countdown.component.d.ts +38 -0
- package/lib/components/atoms/countdown/types.d.ts +108 -0
- package/lib/components/atoms/fab/fab.component.d.ts +16 -0
- package/lib/components/atoms/fab/types.d.ts +45 -0
- package/lib/components/atoms/price-tag/price-tag.component.d.ts +16 -0
- package/lib/components/atoms/price-tag/types.d.ts +59 -0
- package/lib/components/atoms/progress-ring/progress-ring.component.d.ts +20 -0
- package/lib/components/atoms/progress-ring/types.d.ts +24 -0
- package/lib/components/atoms/qr-code/qr-code.component.d.ts +36 -0
- package/lib/components/atoms/qr-code/types.d.ts +124 -0
- package/lib/components/atoms/skeleton/skeleton.component.d.ts +12 -0
- package/lib/components/atoms/skeleton/types.d.ts +29 -0
- package/lib/components/molecules/accordion/accordion.component.d.ts +19 -0
- package/lib/components/molecules/accordion/types.d.ts +47 -0
- package/lib/components/molecules/breadcrumb/breadcrumb.component.d.ts +22 -0
- package/lib/components/molecules/breadcrumb/types.d.ts +45 -0
- package/lib/components/molecules/chip-group/chip-group.component.d.ts +22 -0
- package/lib/components/molecules/chip-group/types.d.ts +65 -0
- package/lib/components/molecules/comment/comment.component.d.ts +42 -0
- package/lib/components/molecules/comment/types.d.ts +171 -0
- package/lib/components/molecules/currency-input/currency-input.component.d.ts +43 -0
- package/lib/components/molecules/currency-input/types.d.ts +96 -0
- package/lib/components/molecules/date-range-input/date-range-input.component.d.ts +42 -0
- package/lib/components/molecules/date-range-input/types.d.ts +109 -0
- package/lib/components/molecules/glow-card/glow-card.component.d.ts +51 -0
- package/lib/components/molecules/glow-card/types.d.ts +92 -0
- package/lib/components/molecules/number-stepper/number-stepper.component.d.ts +34 -0
- package/lib/components/molecules/number-stepper/types.d.ts +88 -0
- package/lib/components/molecules/pagination/pagination.component.d.ts +15 -0
- package/lib/components/molecules/pagination/types.d.ts +41 -0
- package/lib/components/molecules/participant-card/participant-card.component.d.ts +26 -0
- package/lib/components/molecules/participant-card/types.d.ts +132 -0
- package/lib/components/molecules/phone-input/phone-input.component.d.ts +38 -0
- package/lib/components/molecules/phone-input/types.d.ts +98 -0
- package/lib/components/molecules/quote-box/quote-box.component.d.ts +26 -0
- package/lib/components/molecules/raffle-status-card/raffle-status-card.component.d.ts +22 -0
- package/lib/components/molecules/raffle-status-card/types.d.ts +108 -0
- package/lib/components/molecules/range-input/range-input.component.d.ts +30 -0
- package/lib/components/molecules/range-input/types.d.ts +59 -0
- package/lib/components/molecules/rating/rating.component.d.ts +17 -0
- package/lib/components/molecules/rating/types.d.ts +41 -0
- package/lib/components/molecules/segment-control/segment-control.component.d.ts +30 -0
- package/lib/components/molecules/segment-control/types.d.ts +46 -0
- package/lib/components/molecules/share-buttons/share-buttons.component.d.ts +22 -0
- package/lib/components/molecules/share-buttons/types.d.ts +108 -0
- package/lib/components/molecules/stats-card/stats-card.component.d.ts +14 -0
- package/lib/components/molecules/stats-card/types.d.ts +41 -0
- package/lib/components/molecules/stepper/stepper.component.d.ts +21 -0
- package/lib/components/molecules/stepper/types.d.ts +66 -0
- package/lib/components/molecules/tabs/tabs.component.d.ts +17 -0
- package/lib/components/molecules/tabs/types.d.ts +45 -0
- package/lib/components/molecules/textarea-input/textarea-input.component.d.ts +27 -0
- package/lib/components/molecules/textarea-input/types.d.ts +74 -0
- package/lib/components/molecules/ticket-grid/ticket-grid.component.d.ts +41 -0
- package/lib/components/molecules/ticket-grid/types.d.ts +122 -0
- package/lib/components/molecules/timeline/timeline.component.d.ts +14 -0
- package/lib/components/molecules/timeline/types.d.ts +39 -0
- package/lib/components/molecules/toggle-input/toggle-input.component.d.ts +24 -0
- package/lib/components/molecules/toggle-input/types.d.ts +30 -0
- package/lib/components/molecules/winner-display/types.d.ts +103 -0
- package/lib/components/molecules/winner-display/winner-display.component.d.ts +37 -0
- package/lib/components/organisms/article/article.component.d.ts +1 -1
- package/lib/components/organisms/comment-section/comment-section.component.d.ts +52 -0
- package/lib/components/organisms/comment-section/types.d.ts +144 -0
- package/lib/components/organisms/data-table/data-table.component.d.ts +46 -0
- package/lib/components/organisms/data-table/types.d.ts +205 -0
- package/lib/components/types.d.ts +21 -15
- package/lib/services/confirmation-dialog/confirmation-dialog.service.d.ts +71 -0
- package/lib/services/confirmation-dialog/types.d.ts +61 -0
- package/lib/services/modal/modal.service.d.ts +98 -0
- package/lib/services/modal/simple-modal-content.component.d.ts +19 -0
- package/lib/services/modal/types.d.ts +155 -0
- package/lib/services/qr-generator/qr-generator.service.d.ts +115 -0
- package/lib/services/qr-generator/types.d.ts +141 -0
- package/package.json +11 -4
- package/public-api.d.ts +72 -2
- package/LICENSE +0 -21
|
@@ -0,0 +1,578 @@
|
|
|
1
|
+
import { Component, Input, Output, EventEmitter, inject } from '@angular/core';
|
|
2
|
+
import { CommonModule } from '@angular/common';
|
|
3
|
+
import { FormsModule } from '@angular/forms';
|
|
4
|
+
import { IonIcon, IonButton, IonBadge, IonTextarea, IonItem, IonSelect, IonSelectOption, IonSpinner, IonInfiniteScroll, IonInfiniteScrollContent, } from '@ionic/angular/standalone';
|
|
5
|
+
import { addIcons } from 'ionicons';
|
|
6
|
+
import { chatbubblesOutline, filterOutline, sendOutline, chatbubbleEllipsesOutline, swapVerticalOutline, } from 'ionicons/icons';
|
|
7
|
+
import { CommentComponent } from '../../molecules/comment/comment.component';
|
|
8
|
+
import { AvatarComponent } from '../../atoms/avatar/avatar.component';
|
|
9
|
+
import { SkeletonComponent } from '../../atoms/skeleton/skeleton.component';
|
|
10
|
+
import { LangService } from '../../../services/lang-provider/lang-provider.service';
|
|
11
|
+
import * as i0 from "@angular/core";
|
|
12
|
+
import * as i1 from "@angular/forms";
|
|
13
|
+
addIcons({
|
|
14
|
+
chatbubblesOutline,
|
|
15
|
+
filterOutline,
|
|
16
|
+
sendOutline,
|
|
17
|
+
chatbubbleEllipsesOutline,
|
|
18
|
+
swapVerticalOutline,
|
|
19
|
+
});
|
|
20
|
+
/**
|
|
21
|
+
* val-comment-section
|
|
22
|
+
*
|
|
23
|
+
* An organism component that provides a complete comment section with:
|
|
24
|
+
* - Header with title and count
|
|
25
|
+
* - Sort/filter options
|
|
26
|
+
* - New comment input
|
|
27
|
+
* - Comments list with val-comment
|
|
28
|
+
* - Load more pagination
|
|
29
|
+
* - Empty state
|
|
30
|
+
*
|
|
31
|
+
* @example Basic usage
|
|
32
|
+
* <val-comment-section [props]="{
|
|
33
|
+
* title: 'Comments',
|
|
34
|
+
* count: 42,
|
|
35
|
+
* comments: commentsArray,
|
|
36
|
+
* showInput: true
|
|
37
|
+
* }"></val-comment-section>
|
|
38
|
+
*
|
|
39
|
+
* @example With sorting
|
|
40
|
+
* <val-comment-section [props]="{
|
|
41
|
+
* title: 'Reviews',
|
|
42
|
+
* count: 128,
|
|
43
|
+
* comments: reviews,
|
|
44
|
+
* sortOptions: [
|
|
45
|
+
* { token: 'newest', label: 'Newest first' },
|
|
46
|
+
* { token: 'oldest', label: 'Oldest first' },
|
|
47
|
+
* { token: 'popular', label: 'Most popular' }
|
|
48
|
+
* ],
|
|
49
|
+
* selectedSort: 'newest'
|
|
50
|
+
* }" (sortChange)="onSort($event)"></val-comment-section>
|
|
51
|
+
*
|
|
52
|
+
* @input props: CommentSectionMetadata - Configuration for the section
|
|
53
|
+
* @output sortChange - Sort option changed
|
|
54
|
+
* @output commentSubmit - New comment submitted
|
|
55
|
+
* @output loadMore - Load more clicked
|
|
56
|
+
* @output authorClick - Comment author clicked (bubbled from val-comment)
|
|
57
|
+
* @output reactionClick - Reaction clicked (bubbled)
|
|
58
|
+
* @output actionClick - Action clicked (bubbled)
|
|
59
|
+
* @output menuItemClick - Menu item clicked (bubbled)
|
|
60
|
+
* @output commentLoadMore - Load more replies clicked (bubbled)
|
|
61
|
+
* @output collapseToggle - Comment collapse toggled (bubbled)
|
|
62
|
+
*/
|
|
63
|
+
export class CommentSectionComponent {
|
|
64
|
+
constructor() {
|
|
65
|
+
// Section events
|
|
66
|
+
this.sortChange = new EventEmitter();
|
|
67
|
+
this.commentSubmit = new EventEmitter();
|
|
68
|
+
this.loadMore = new EventEmitter();
|
|
69
|
+
// Bubbled events from val-comment
|
|
70
|
+
this.authorClick = new EventEmitter();
|
|
71
|
+
this.reactionClick = new EventEmitter();
|
|
72
|
+
this.actionClick = new EventEmitter();
|
|
73
|
+
this.menuItemClick = new EventEmitter();
|
|
74
|
+
this.commentLoadMore = new EventEmitter();
|
|
75
|
+
this.collapseToggle = new EventEmitter();
|
|
76
|
+
// Reply state
|
|
77
|
+
this.replyStart = new EventEmitter();
|
|
78
|
+
this.newCommentText = '';
|
|
79
|
+
this.replyingTo = null;
|
|
80
|
+
this.displayTitle = '';
|
|
81
|
+
this.displayLoadMoreLabel = '';
|
|
82
|
+
this.langSubscription = null;
|
|
83
|
+
this.langService = inject(LangService);
|
|
84
|
+
this.infiniteScrollEvent = null;
|
|
85
|
+
}
|
|
86
|
+
ngOnInit() {
|
|
87
|
+
this.updateDisplayTexts();
|
|
88
|
+
if (this.hasReactiveContent()) {
|
|
89
|
+
this.langSubscription = this.langService.currentLang$.subscribe(() => {
|
|
90
|
+
this.updateDisplayTexts();
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
ngOnDestroy() {
|
|
95
|
+
this.langSubscription?.unsubscribe();
|
|
96
|
+
}
|
|
97
|
+
hasReactiveContent() {
|
|
98
|
+
return !!((this.props.titleContentKey && this.props.contentClass) ||
|
|
99
|
+
(this.props.loadMoreContentKey && this.props.contentClass));
|
|
100
|
+
}
|
|
101
|
+
updateDisplayTexts() {
|
|
102
|
+
// Title
|
|
103
|
+
if (this.props.titleContentKey && this.props.contentClass) {
|
|
104
|
+
this.displayTitle = this.langService.getText(this.props.contentClass, this.props.titleContentKey, this.props.titleContentFallback || this.props.title || 'Comments');
|
|
105
|
+
}
|
|
106
|
+
else {
|
|
107
|
+
this.displayTitle = this.props.title || 'Comments';
|
|
108
|
+
}
|
|
109
|
+
// Load more label
|
|
110
|
+
if (this.props.loadMoreContentKey && this.props.contentClass) {
|
|
111
|
+
this.displayLoadMoreLabel = this.langService.getText(this.props.contentClass, this.props.loadMoreContentKey, this.props.loadMoreLabel || 'Load more comments');
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
this.displayLoadMoreLabel = this.props.loadMoreLabel || 'Load more comments';
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
formatCount(count) {
|
|
118
|
+
if (count >= 1000000) {
|
|
119
|
+
return (count / 1000000).toFixed(1).replace(/\.0$/, '') + 'M';
|
|
120
|
+
}
|
|
121
|
+
if (count >= 1000) {
|
|
122
|
+
return (count / 1000).toFixed(1).replace(/\.0$/, '') + 'K';
|
|
123
|
+
}
|
|
124
|
+
return count.toString();
|
|
125
|
+
}
|
|
126
|
+
getSortOptionLabel(option) {
|
|
127
|
+
if (option.contentKey && option.contentClass) {
|
|
128
|
+
return this.langService.getText(option.contentClass, option.contentKey, option.contentFallback || option.label);
|
|
129
|
+
}
|
|
130
|
+
return option.label;
|
|
131
|
+
}
|
|
132
|
+
getInputPlaceholder() {
|
|
133
|
+
const config = this.props.inputConfig;
|
|
134
|
+
if (config?.placeholderContentKey && config?.contentClass) {
|
|
135
|
+
return this.langService.getText(config.contentClass, config.placeholderContentKey, config.placeholder || 'Write a comment...');
|
|
136
|
+
}
|
|
137
|
+
return config?.placeholder || 'Write a comment...';
|
|
138
|
+
}
|
|
139
|
+
getSubmitLabel() {
|
|
140
|
+
const config = this.props.inputConfig;
|
|
141
|
+
if (config?.submitLabelContentKey && config?.contentClass) {
|
|
142
|
+
return this.langService.getText(config.contentClass, config.submitLabelContentKey, config.submitLabel || 'Post');
|
|
143
|
+
}
|
|
144
|
+
return config?.submitLabel || 'Post';
|
|
145
|
+
}
|
|
146
|
+
getEmptyTitle() {
|
|
147
|
+
const empty = this.props.emptyState;
|
|
148
|
+
if (empty?.titleContentKey && empty?.contentClass) {
|
|
149
|
+
return this.langService.getText(empty.contentClass, empty.titleContentKey, empty.title || 'No comments yet');
|
|
150
|
+
}
|
|
151
|
+
return empty?.title || 'No comments yet';
|
|
152
|
+
}
|
|
153
|
+
getEmptyMessage() {
|
|
154
|
+
const empty = this.props.emptyState;
|
|
155
|
+
if (empty?.messageContentKey && empty?.contentClass) {
|
|
156
|
+
return this.langService.getText(empty.contentClass, empty.messageContentKey, empty.message || 'Be the first to share your thoughts!');
|
|
157
|
+
}
|
|
158
|
+
return empty?.message || 'Be the first to share your thoughts!';
|
|
159
|
+
}
|
|
160
|
+
getSkeletonArray() {
|
|
161
|
+
const count = this.props.skeletonCount || 3;
|
|
162
|
+
return Array(count).fill(0).map((_, i) => i);
|
|
163
|
+
}
|
|
164
|
+
canSubmit() {
|
|
165
|
+
const minLength = this.props.inputConfig?.minLength || 1;
|
|
166
|
+
return (this.newCommentText.trim().length >= minLength &&
|
|
167
|
+
!this.props.loading &&
|
|
168
|
+
!this.props.inputConfig?.disabled);
|
|
169
|
+
}
|
|
170
|
+
isNearLimit() {
|
|
171
|
+
const maxLength = this.props.inputConfig?.maxLength || 2000;
|
|
172
|
+
return this.newCommentText.length > maxLength * 0.9;
|
|
173
|
+
}
|
|
174
|
+
onSortChange(event) {
|
|
175
|
+
const selectedToken = event.detail.value;
|
|
176
|
+
const option = this.props.sortOptions?.find((o) => o.token === selectedToken);
|
|
177
|
+
if (option) {
|
|
178
|
+
this.sortChange.emit({
|
|
179
|
+
option,
|
|
180
|
+
previousSort: this.props.selectedSort,
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
onSubmitComment() {
|
|
185
|
+
if (!this.canSubmit())
|
|
186
|
+
return;
|
|
187
|
+
this.commentSubmit.emit({
|
|
188
|
+
content: this.newCommentText.trim(),
|
|
189
|
+
parentToken: this.replyingTo || undefined,
|
|
190
|
+
sectionToken: this.props.token,
|
|
191
|
+
});
|
|
192
|
+
this.newCommentText = '';
|
|
193
|
+
this.replyingTo = null;
|
|
194
|
+
}
|
|
195
|
+
onCommentAction(event) {
|
|
196
|
+
// Check if it's a reply action
|
|
197
|
+
if (event.action.token === 'reply') {
|
|
198
|
+
this.replyingTo = event.commentToken;
|
|
199
|
+
this.replyStart.emit({ commentToken: event.commentToken });
|
|
200
|
+
}
|
|
201
|
+
this.actionClick.emit(event);
|
|
202
|
+
}
|
|
203
|
+
onLoadMore() {
|
|
204
|
+
this.loadMore.emit({
|
|
205
|
+
sectionToken: this.props.token,
|
|
206
|
+
currentCount: this.props.comments?.length || 0,
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
onInfiniteScroll(event) {
|
|
210
|
+
this.loadMore.emit({
|
|
211
|
+
sectionToken: this.props.token,
|
|
212
|
+
currentCount: this.props.comments?.length || 0,
|
|
213
|
+
});
|
|
214
|
+
// The parent component should call completeInfiniteScroll() when done loading
|
|
215
|
+
// Store reference to complete the infinite scroll
|
|
216
|
+
this.infiniteScrollEvent = event;
|
|
217
|
+
}
|
|
218
|
+
// Call this method from parent after loading more comments
|
|
219
|
+
completeInfiniteScroll() {
|
|
220
|
+
if (this.infiniteScrollEvent) {
|
|
221
|
+
this.infiniteScrollEvent.target.complete();
|
|
222
|
+
this.infiniteScrollEvent = null;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
// Method to programmatically start a reply
|
|
226
|
+
startReply(commentToken) {
|
|
227
|
+
this.replyingTo = commentToken;
|
|
228
|
+
}
|
|
229
|
+
// Method to cancel reply
|
|
230
|
+
cancelReply() {
|
|
231
|
+
this.replyingTo = null;
|
|
232
|
+
}
|
|
233
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: CommentSectionComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
234
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: CommentSectionComponent, isStandalone: true, selector: "val-comment-section", inputs: { props: "props" }, outputs: { sortChange: "sortChange", commentSubmit: "commentSubmit", loadMore: "loadMore", authorClick: "authorClick", reactionClick: "reactionClick", actionClick: "actionClick", menuItemClick: "menuItemClick", commentLoadMore: "commentLoadMore", collapseToggle: "collapseToggle", replyStart: "replyStart" }, ngImport: i0, template: `
|
|
235
|
+
<div class="comment-section" [class.loading]="props.loading">
|
|
236
|
+
<!-- Header -->
|
|
237
|
+
<div class="section-header">
|
|
238
|
+
<div class="header-title">
|
|
239
|
+
<ion-icon name="chatbubbles-outline" class="title-icon"></ion-icon>
|
|
240
|
+
<h3 class="title">{{ displayTitle }}</h3>
|
|
241
|
+
@if (props.showCount !== false && props.count !== undefined) {
|
|
242
|
+
<ion-badge color="medium" class="count-badge">
|
|
243
|
+
{{ formatCount(props.count) }}
|
|
244
|
+
</ion-badge>
|
|
245
|
+
}
|
|
246
|
+
</div>
|
|
247
|
+
|
|
248
|
+
@if (props.sortOptions && props.sortOptions.length > 0) {
|
|
249
|
+
<div class="header-actions">
|
|
250
|
+
<ion-item lines="none" class="sort-select-item">
|
|
251
|
+
<ion-icon name="swap-vertical-outline" slot="start" class="sort-icon"></ion-icon>
|
|
252
|
+
<ion-select
|
|
253
|
+
[value]="props.selectedSort"
|
|
254
|
+
[placeholder]="props.sortLabel || 'Sort by'"
|
|
255
|
+
interface="popover"
|
|
256
|
+
(ionChange)="onSortChange($event)"
|
|
257
|
+
>
|
|
258
|
+
@for (option of props.sortOptions; track option.token) {
|
|
259
|
+
<ion-select-option [value]="option.token">
|
|
260
|
+
{{ getSortOptionLabel(option) }}
|
|
261
|
+
</ion-select-option>
|
|
262
|
+
}
|
|
263
|
+
</ion-select>
|
|
264
|
+
</ion-item>
|
|
265
|
+
</div>
|
|
266
|
+
}
|
|
267
|
+
</div>
|
|
268
|
+
|
|
269
|
+
<!-- New Comment Input -->
|
|
270
|
+
@if (props.showInput !== false) {
|
|
271
|
+
<div class="new-comment-section">
|
|
272
|
+
<div class="input-wrapper">
|
|
273
|
+
@if (props.inputConfig?.currentUser?.avatar) {
|
|
274
|
+
<div class="input-avatar">
|
|
275
|
+
<val-avatar [props]="props.inputConfig.currentUser.avatar"></val-avatar>
|
|
276
|
+
</div>
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
<div class="input-container">
|
|
280
|
+
<ion-textarea
|
|
281
|
+
[(ngModel)]="newCommentText"
|
|
282
|
+
[placeholder]="getInputPlaceholder()"
|
|
283
|
+
[maxlength]="props.inputConfig?.maxLength || 2000"
|
|
284
|
+
[disabled]="props.inputConfig?.disabled || props.loading"
|
|
285
|
+
[autoGrow]="true"
|
|
286
|
+
rows="2"
|
|
287
|
+
class="comment-textarea"
|
|
288
|
+
></ion-textarea>
|
|
289
|
+
|
|
290
|
+
<div class="input-actions">
|
|
291
|
+
@if (props.inputConfig?.showCounter && props.inputConfig?.maxLength) {
|
|
292
|
+
<span class="char-counter" [class.warning]="isNearLimit()">
|
|
293
|
+
{{ newCommentText.length }} / {{ props.inputConfig.maxLength }}
|
|
294
|
+
</span>
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
<ion-button
|
|
298
|
+
[color]="props.inputConfig?.submitColor || props.color || 'primary'"
|
|
299
|
+
[disabled]="!canSubmit()"
|
|
300
|
+
size="small"
|
|
301
|
+
(click)="onSubmitComment()"
|
|
302
|
+
>
|
|
303
|
+
<ion-icon name="send-outline" slot="start"></ion-icon>
|
|
304
|
+
{{ getSubmitLabel() }}
|
|
305
|
+
</ion-button>
|
|
306
|
+
</div>
|
|
307
|
+
</div>
|
|
308
|
+
</div>
|
|
309
|
+
</div>
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
@if (props.loading) {
|
|
313
|
+
<div class="loading-state">
|
|
314
|
+
@for (i of getSkeletonArray(); track i) {
|
|
315
|
+
<div class="skeleton-comment">
|
|
316
|
+
<val-skeleton [props]="{ type: 'avatar', width: '36px', height: '36px' }"></val-skeleton>
|
|
317
|
+
<div class="skeleton-content">
|
|
318
|
+
<val-skeleton [props]="{ type: 'text', width: '120px', height: '14px' }"></val-skeleton>
|
|
319
|
+
<val-skeleton [props]="{ type: 'paragraph', lines: 2 }"></val-skeleton>
|
|
320
|
+
</div>
|
|
321
|
+
</div>
|
|
322
|
+
}
|
|
323
|
+
</div>
|
|
324
|
+
} @else if (props.comments && props.comments.length > 0) {
|
|
325
|
+
<div class="comments-list" [class.with-dividers]="props.showDividers">
|
|
326
|
+
@for (comment of props.comments; track comment.token) {
|
|
327
|
+
<val-comment
|
|
328
|
+
[props]="comment"
|
|
329
|
+
(authorClick)="authorClick.emit($event)"
|
|
330
|
+
(reactionClick)="reactionClick.emit($event)"
|
|
331
|
+
(actionClick)="onCommentAction($event)"
|
|
332
|
+
(menuItemClick)="menuItemClick.emit($event)"
|
|
333
|
+
(loadMoreClick)="commentLoadMore.emit($event)"
|
|
334
|
+
(collapseToggle)="collapseToggle.emit($event)"
|
|
335
|
+
></val-comment>
|
|
336
|
+
|
|
337
|
+
@if (props.showDividers && !$last) {
|
|
338
|
+
<div class="comment-divider"></div>
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
@if (props.hasMore && props.paginationMode !== 'infinite') {
|
|
343
|
+
<div class="load-more-section">
|
|
344
|
+
@if (props.loadingMore) {
|
|
345
|
+
<ion-spinner name="crescent" [color]="props.color || 'primary'"></ion-spinner>
|
|
346
|
+
} @else {
|
|
347
|
+
<ion-button
|
|
348
|
+
fill="outline"
|
|
349
|
+
[color]="props.color || 'primary'"
|
|
350
|
+
expand="block"
|
|
351
|
+
(click)="onLoadMore()"
|
|
352
|
+
>
|
|
353
|
+
{{ displayLoadMoreLabel }}
|
|
354
|
+
</ion-button>
|
|
355
|
+
}
|
|
356
|
+
</div>
|
|
357
|
+
}
|
|
358
|
+
</div>
|
|
359
|
+
|
|
360
|
+
@if (props.paginationMode === 'infinite') {
|
|
361
|
+
<ion-infinite-scroll
|
|
362
|
+
[threshold]="props.infiniteScrollThreshold || '100px'"
|
|
363
|
+
[position]="props.infiniteScrollPosition || 'bottom'"
|
|
364
|
+
[disabled]="!props.hasMore"
|
|
365
|
+
(ionInfinite)="onInfiniteScroll($event)"
|
|
366
|
+
>
|
|
367
|
+
<ion-infinite-scroll-content
|
|
368
|
+
[loadingSpinner]="'crescent'"
|
|
369
|
+
[loadingText]="displayLoadMoreLabel"
|
|
370
|
+
></ion-infinite-scroll-content>
|
|
371
|
+
</ion-infinite-scroll>
|
|
372
|
+
}
|
|
373
|
+
} @else {
|
|
374
|
+
<div class="empty-state">
|
|
375
|
+
<ion-icon
|
|
376
|
+
[name]="props.emptyState?.icon || 'chatbubble-ellipses-outline'"
|
|
377
|
+
class="empty-icon"
|
|
378
|
+
></ion-icon>
|
|
379
|
+
<h4 class="empty-title">{{ getEmptyTitle() }}</h4>
|
|
380
|
+
<p class="empty-message">{{ getEmptyMessage() }}</p>
|
|
381
|
+
</div>
|
|
382
|
+
}
|
|
383
|
+
</div>
|
|
384
|
+
`, isInline: true, styles: [":host{display:block}.comment-section.loading{pointer-events:none}.section-header{display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:12px;margin-bottom:20px;padding-bottom:16px;border-bottom:1px solid var(--ion-color-light-shade)}.header-title{display:flex;align-items:center;gap:8px}.title-icon{font-size:24px;color:var(--ion-color-primary)}.title{margin:0;font-size:18px;font-weight:600;color:var(--ion-text-color)}.count-badge{font-size:12px;font-weight:600;--padding-start: 8px;--padding-end: 8px}.header-actions{display:flex;align-items:center;gap:8px}.sort-select-item{--padding-start: 0;--padding-end: 0;--inner-padding-end: 0;--background: transparent;--min-height: 36px}.sort-select-item ion-select{--padding-start: 8px;--padding-end: 8px;min-width:140px;font-size:14px}.sort-icon{font-size:18px;color:var(--ion-color-medium);margin-right:4px}.new-comment-section{margin-bottom:24px;padding:16px;background-color:var(--ion-color-light);border-radius:12px}.input-wrapper{display:flex;gap:12px}.input-avatar{flex-shrink:0}.input-avatar val-avatar{--size: 40px}.input-container{flex:1;min-width:0}.comment-textarea{--background: var(--ion-background-color);--padding-start: 12px;--padding-end: 12px;--padding-top: 10px;--padding-bottom: 10px;border-radius:8px;font-size:14px;min-height:60px;border:1px solid var(--ion-color-light-shade);transition:border-color .2s}.comment-textarea:focus-within{border-color:var(--ion-color-primary)}.input-actions{display:flex;align-items:center;justify-content:flex-end;gap:12px;margin-top:10px}.char-counter{font-size:12px;color:var(--ion-color-medium)}.char-counter.warning{color:var(--ion-color-warning);font-weight:500}.loading-state{display:flex;flex-direction:column;gap:20px}.skeleton-comment{display:flex;gap:12px;padding:12px 0}.skeleton-comment .skeleton-content{flex:1;display:flex;flex-direction:column;gap:8px}.comments-list.with-dividers val-comment{padding:16px 0}.comments-list.with-dividers val-comment:first-child{padding-top:0}.comment-divider{height:1px;background-color:var(--ion-color-light-shade);margin:0}.load-more-section{display:flex;justify-content:center;padding:20px 0}.load-more-section ion-button{min-width:200px}.load-more-section ion-spinner{width:28px;height:28px}.empty-state{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:48px 24px;text-align:center}.empty-icon{font-size:64px;color:var(--ion-color-medium);opacity:.5;margin-bottom:16px}.empty-title{margin:0 0 8px;font-size:18px;font-weight:600;color:var(--ion-text-color)}.empty-message{margin:0;font-size:14px;color:var(--ion-color-medium);max-width:300px}@media (max-width: 576px){.section-header{flex-direction:column;align-items:flex-start}.header-actions,.sort-select-item{width:100%}.sort-select-item ion-select{width:100%}.input-wrapper{flex-direction:column}.input-avatar{display:none}.input-actions{flex-direction:column;align-items:stretch}.input-actions ion-button{width:100%}}@media (prefers-color-scheme: dark){.new-comment-section{background-color:var(--ion-color-step-100, #1a1a1a)}.comment-textarea{--background: var(--ion-color-step-50, #121212);border-color:var(--ion-color-step-200, #2a2a2a)}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }, { kind: "component", type: IonBadge, selector: "ion-badge", inputs: ["color", "mode"] }, { kind: "component", type: IonTextarea, selector: "ion-textarea", inputs: ["autoGrow", "autocapitalize", "autofocus", "clearOnEdit", "color", "cols", "counter", "counterFormatter", "debounce", "disabled", "enterkeyhint", "errorText", "fill", "helperText", "inputmode", "label", "labelPlacement", "maxlength", "minlength", "mode", "name", "placeholder", "readonly", "required", "rows", "shape", "spellcheck", "value", "wrap"] }, { kind: "component", type: IonItem, selector: "ion-item", inputs: ["button", "color", "detail", "detailIcon", "disabled", "download", "href", "lines", "mode", "rel", "routerAnimation", "routerDirection", "target", "type"] }, { kind: "component", type: IonSelect, selector: "ion-select", inputs: ["cancelText", "color", "compareWith", "disabled", "errorText", "expandedIcon", "fill", "helperText", "interface", "interfaceOptions", "justify", "label", "labelPlacement", "mode", "multiple", "name", "okText", "placeholder", "selectedText", "shape", "toggleIcon", "value"] }, { kind: "component", type: IonSelectOption, selector: "ion-select-option", inputs: ["disabled", "value"] }, { kind: "component", type: IonSpinner, selector: "ion-spinner", inputs: ["color", "duration", "name", "paused"] }, { kind: "component", type: IonInfiniteScroll, selector: "ion-infinite-scroll", inputs: ["disabled", "position", "threshold"] }, { kind: "component", type: IonInfiniteScrollContent, selector: "ion-infinite-scroll-content", inputs: ["loadingSpinner", "loadingText"] }, { kind: "component", type: CommentComponent, selector: "val-comment", inputs: ["props"], outputs: ["authorClick", "reactionClick", "actionClick", "menuItemClick", "loadMoreClick", "collapseToggle"] }, { kind: "component", type: AvatarComponent, selector: "val-avatar", inputs: ["props"], outputs: ["onClick"] }, { kind: "component", type: SkeletonComponent, selector: "val-skeleton", inputs: ["props"] }] }); }
|
|
385
|
+
}
|
|
386
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: CommentSectionComponent, decorators: [{
|
|
387
|
+
type: Component,
|
|
388
|
+
args: [{ selector: 'val-comment-section', standalone: true, imports: [
|
|
389
|
+
CommonModule,
|
|
390
|
+
FormsModule,
|
|
391
|
+
IonIcon,
|
|
392
|
+
IonButton,
|
|
393
|
+
IonBadge,
|
|
394
|
+
IonTextarea,
|
|
395
|
+
IonItem,
|
|
396
|
+
IonSelect,
|
|
397
|
+
IonSelectOption,
|
|
398
|
+
IonSpinner,
|
|
399
|
+
IonInfiniteScroll,
|
|
400
|
+
IonInfiniteScrollContent,
|
|
401
|
+
CommentComponent,
|
|
402
|
+
AvatarComponent,
|
|
403
|
+
SkeletonComponent,
|
|
404
|
+
], template: `
|
|
405
|
+
<div class="comment-section" [class.loading]="props.loading">
|
|
406
|
+
<!-- Header -->
|
|
407
|
+
<div class="section-header">
|
|
408
|
+
<div class="header-title">
|
|
409
|
+
<ion-icon name="chatbubbles-outline" class="title-icon"></ion-icon>
|
|
410
|
+
<h3 class="title">{{ displayTitle }}</h3>
|
|
411
|
+
@if (props.showCount !== false && props.count !== undefined) {
|
|
412
|
+
<ion-badge color="medium" class="count-badge">
|
|
413
|
+
{{ formatCount(props.count) }}
|
|
414
|
+
</ion-badge>
|
|
415
|
+
}
|
|
416
|
+
</div>
|
|
417
|
+
|
|
418
|
+
@if (props.sortOptions && props.sortOptions.length > 0) {
|
|
419
|
+
<div class="header-actions">
|
|
420
|
+
<ion-item lines="none" class="sort-select-item">
|
|
421
|
+
<ion-icon name="swap-vertical-outline" slot="start" class="sort-icon"></ion-icon>
|
|
422
|
+
<ion-select
|
|
423
|
+
[value]="props.selectedSort"
|
|
424
|
+
[placeholder]="props.sortLabel || 'Sort by'"
|
|
425
|
+
interface="popover"
|
|
426
|
+
(ionChange)="onSortChange($event)"
|
|
427
|
+
>
|
|
428
|
+
@for (option of props.sortOptions; track option.token) {
|
|
429
|
+
<ion-select-option [value]="option.token">
|
|
430
|
+
{{ getSortOptionLabel(option) }}
|
|
431
|
+
</ion-select-option>
|
|
432
|
+
}
|
|
433
|
+
</ion-select>
|
|
434
|
+
</ion-item>
|
|
435
|
+
</div>
|
|
436
|
+
}
|
|
437
|
+
</div>
|
|
438
|
+
|
|
439
|
+
<!-- New Comment Input -->
|
|
440
|
+
@if (props.showInput !== false) {
|
|
441
|
+
<div class="new-comment-section">
|
|
442
|
+
<div class="input-wrapper">
|
|
443
|
+
@if (props.inputConfig?.currentUser?.avatar) {
|
|
444
|
+
<div class="input-avatar">
|
|
445
|
+
<val-avatar [props]="props.inputConfig.currentUser.avatar"></val-avatar>
|
|
446
|
+
</div>
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
<div class="input-container">
|
|
450
|
+
<ion-textarea
|
|
451
|
+
[(ngModel)]="newCommentText"
|
|
452
|
+
[placeholder]="getInputPlaceholder()"
|
|
453
|
+
[maxlength]="props.inputConfig?.maxLength || 2000"
|
|
454
|
+
[disabled]="props.inputConfig?.disabled || props.loading"
|
|
455
|
+
[autoGrow]="true"
|
|
456
|
+
rows="2"
|
|
457
|
+
class="comment-textarea"
|
|
458
|
+
></ion-textarea>
|
|
459
|
+
|
|
460
|
+
<div class="input-actions">
|
|
461
|
+
@if (props.inputConfig?.showCounter && props.inputConfig?.maxLength) {
|
|
462
|
+
<span class="char-counter" [class.warning]="isNearLimit()">
|
|
463
|
+
{{ newCommentText.length }} / {{ props.inputConfig.maxLength }}
|
|
464
|
+
</span>
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
<ion-button
|
|
468
|
+
[color]="props.inputConfig?.submitColor || props.color || 'primary'"
|
|
469
|
+
[disabled]="!canSubmit()"
|
|
470
|
+
size="small"
|
|
471
|
+
(click)="onSubmitComment()"
|
|
472
|
+
>
|
|
473
|
+
<ion-icon name="send-outline" slot="start"></ion-icon>
|
|
474
|
+
{{ getSubmitLabel() }}
|
|
475
|
+
</ion-button>
|
|
476
|
+
</div>
|
|
477
|
+
</div>
|
|
478
|
+
</div>
|
|
479
|
+
</div>
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
@if (props.loading) {
|
|
483
|
+
<div class="loading-state">
|
|
484
|
+
@for (i of getSkeletonArray(); track i) {
|
|
485
|
+
<div class="skeleton-comment">
|
|
486
|
+
<val-skeleton [props]="{ type: 'avatar', width: '36px', height: '36px' }"></val-skeleton>
|
|
487
|
+
<div class="skeleton-content">
|
|
488
|
+
<val-skeleton [props]="{ type: 'text', width: '120px', height: '14px' }"></val-skeleton>
|
|
489
|
+
<val-skeleton [props]="{ type: 'paragraph', lines: 2 }"></val-skeleton>
|
|
490
|
+
</div>
|
|
491
|
+
</div>
|
|
492
|
+
}
|
|
493
|
+
</div>
|
|
494
|
+
} @else if (props.comments && props.comments.length > 0) {
|
|
495
|
+
<div class="comments-list" [class.with-dividers]="props.showDividers">
|
|
496
|
+
@for (comment of props.comments; track comment.token) {
|
|
497
|
+
<val-comment
|
|
498
|
+
[props]="comment"
|
|
499
|
+
(authorClick)="authorClick.emit($event)"
|
|
500
|
+
(reactionClick)="reactionClick.emit($event)"
|
|
501
|
+
(actionClick)="onCommentAction($event)"
|
|
502
|
+
(menuItemClick)="menuItemClick.emit($event)"
|
|
503
|
+
(loadMoreClick)="commentLoadMore.emit($event)"
|
|
504
|
+
(collapseToggle)="collapseToggle.emit($event)"
|
|
505
|
+
></val-comment>
|
|
506
|
+
|
|
507
|
+
@if (props.showDividers && !$last) {
|
|
508
|
+
<div class="comment-divider"></div>
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
@if (props.hasMore && props.paginationMode !== 'infinite') {
|
|
513
|
+
<div class="load-more-section">
|
|
514
|
+
@if (props.loadingMore) {
|
|
515
|
+
<ion-spinner name="crescent" [color]="props.color || 'primary'"></ion-spinner>
|
|
516
|
+
} @else {
|
|
517
|
+
<ion-button
|
|
518
|
+
fill="outline"
|
|
519
|
+
[color]="props.color || 'primary'"
|
|
520
|
+
expand="block"
|
|
521
|
+
(click)="onLoadMore()"
|
|
522
|
+
>
|
|
523
|
+
{{ displayLoadMoreLabel }}
|
|
524
|
+
</ion-button>
|
|
525
|
+
}
|
|
526
|
+
</div>
|
|
527
|
+
}
|
|
528
|
+
</div>
|
|
529
|
+
|
|
530
|
+
@if (props.paginationMode === 'infinite') {
|
|
531
|
+
<ion-infinite-scroll
|
|
532
|
+
[threshold]="props.infiniteScrollThreshold || '100px'"
|
|
533
|
+
[position]="props.infiniteScrollPosition || 'bottom'"
|
|
534
|
+
[disabled]="!props.hasMore"
|
|
535
|
+
(ionInfinite)="onInfiniteScroll($event)"
|
|
536
|
+
>
|
|
537
|
+
<ion-infinite-scroll-content
|
|
538
|
+
[loadingSpinner]="'crescent'"
|
|
539
|
+
[loadingText]="displayLoadMoreLabel"
|
|
540
|
+
></ion-infinite-scroll-content>
|
|
541
|
+
</ion-infinite-scroll>
|
|
542
|
+
}
|
|
543
|
+
} @else {
|
|
544
|
+
<div class="empty-state">
|
|
545
|
+
<ion-icon
|
|
546
|
+
[name]="props.emptyState?.icon || 'chatbubble-ellipses-outline'"
|
|
547
|
+
class="empty-icon"
|
|
548
|
+
></ion-icon>
|
|
549
|
+
<h4 class="empty-title">{{ getEmptyTitle() }}</h4>
|
|
550
|
+
<p class="empty-message">{{ getEmptyMessage() }}</p>
|
|
551
|
+
</div>
|
|
552
|
+
}
|
|
553
|
+
</div>
|
|
554
|
+
`, styles: [":host{display:block}.comment-section.loading{pointer-events:none}.section-header{display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:12px;margin-bottom:20px;padding-bottom:16px;border-bottom:1px solid var(--ion-color-light-shade)}.header-title{display:flex;align-items:center;gap:8px}.title-icon{font-size:24px;color:var(--ion-color-primary)}.title{margin:0;font-size:18px;font-weight:600;color:var(--ion-text-color)}.count-badge{font-size:12px;font-weight:600;--padding-start: 8px;--padding-end: 8px}.header-actions{display:flex;align-items:center;gap:8px}.sort-select-item{--padding-start: 0;--padding-end: 0;--inner-padding-end: 0;--background: transparent;--min-height: 36px}.sort-select-item ion-select{--padding-start: 8px;--padding-end: 8px;min-width:140px;font-size:14px}.sort-icon{font-size:18px;color:var(--ion-color-medium);margin-right:4px}.new-comment-section{margin-bottom:24px;padding:16px;background-color:var(--ion-color-light);border-radius:12px}.input-wrapper{display:flex;gap:12px}.input-avatar{flex-shrink:0}.input-avatar val-avatar{--size: 40px}.input-container{flex:1;min-width:0}.comment-textarea{--background: var(--ion-background-color);--padding-start: 12px;--padding-end: 12px;--padding-top: 10px;--padding-bottom: 10px;border-radius:8px;font-size:14px;min-height:60px;border:1px solid var(--ion-color-light-shade);transition:border-color .2s}.comment-textarea:focus-within{border-color:var(--ion-color-primary)}.input-actions{display:flex;align-items:center;justify-content:flex-end;gap:12px;margin-top:10px}.char-counter{font-size:12px;color:var(--ion-color-medium)}.char-counter.warning{color:var(--ion-color-warning);font-weight:500}.loading-state{display:flex;flex-direction:column;gap:20px}.skeleton-comment{display:flex;gap:12px;padding:12px 0}.skeleton-comment .skeleton-content{flex:1;display:flex;flex-direction:column;gap:8px}.comments-list.with-dividers val-comment{padding:16px 0}.comments-list.with-dividers val-comment:first-child{padding-top:0}.comment-divider{height:1px;background-color:var(--ion-color-light-shade);margin:0}.load-more-section{display:flex;justify-content:center;padding:20px 0}.load-more-section ion-button{min-width:200px}.load-more-section ion-spinner{width:28px;height:28px}.empty-state{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:48px 24px;text-align:center}.empty-icon{font-size:64px;color:var(--ion-color-medium);opacity:.5;margin-bottom:16px}.empty-title{margin:0 0 8px;font-size:18px;font-weight:600;color:var(--ion-text-color)}.empty-message{margin:0;font-size:14px;color:var(--ion-color-medium);max-width:300px}@media (max-width: 576px){.section-header{flex-direction:column;align-items:flex-start}.header-actions,.sort-select-item{width:100%}.sort-select-item ion-select{width:100%}.input-wrapper{flex-direction:column}.input-avatar{display:none}.input-actions{flex-direction:column;align-items:stretch}.input-actions ion-button{width:100%}}@media (prefers-color-scheme: dark){.new-comment-section{background-color:var(--ion-color-step-100, #1a1a1a)}.comment-textarea{--background: var(--ion-color-step-50, #121212);border-color:var(--ion-color-step-200, #2a2a2a)}}\n"] }]
|
|
555
|
+
}], propDecorators: { props: [{
|
|
556
|
+
type: Input
|
|
557
|
+
}], sortChange: [{
|
|
558
|
+
type: Output
|
|
559
|
+
}], commentSubmit: [{
|
|
560
|
+
type: Output
|
|
561
|
+
}], loadMore: [{
|
|
562
|
+
type: Output
|
|
563
|
+
}], authorClick: [{
|
|
564
|
+
type: Output
|
|
565
|
+
}], reactionClick: [{
|
|
566
|
+
type: Output
|
|
567
|
+
}], actionClick: [{
|
|
568
|
+
type: Output
|
|
569
|
+
}], menuItemClick: [{
|
|
570
|
+
type: Output
|
|
571
|
+
}], commentLoadMore: [{
|
|
572
|
+
type: Output
|
|
573
|
+
}], collapseToggle: [{
|
|
574
|
+
type: Output
|
|
575
|
+
}], replyStart: [{
|
|
576
|
+
type: Output
|
|
577
|
+
}] } });
|
|
578
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29tbWVudC1zZWN0aW9uLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uL3NyYy9saWIvY29tcG9uZW50cy9vcmdhbmlzbXMvY29tbWVudC1zZWN0aW9uL2NvbW1lbnQtc2VjdGlvbi5jb21wb25lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFNBQVMsRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFFLFlBQVksRUFBcUIsTUFBTSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ2xHLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUMvQyxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDN0MsT0FBTyxFQUNMLE9BQU8sRUFDUCxTQUFTLEVBQ1QsUUFBUSxFQUNSLFdBQVcsRUFDWCxPQUFPLEVBQ1AsU0FBUyxFQUNULGVBQWUsRUFDZixVQUFVLEVBQ1YsaUJBQWlCLEVBQ2pCLHdCQUF3QixHQUN6QixNQUFNLDJCQUEyQixDQUFDO0FBRW5DLE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSxVQUFVLENBQUM7QUFDcEMsT0FBTyxFQUNMLGtCQUFrQixFQUNsQixhQUFhLEVBQ2IsV0FBVyxFQUNYLHlCQUF5QixFQUN6QixtQkFBbUIsR0FDcEIsTUFBTSxnQkFBZ0IsQ0FBQztBQUV4QixPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSwyQ0FBMkMsQ0FBQztBQUM3RSxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0scUNBQXFDLENBQUM7QUFDdEUsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0seUNBQXlDLENBQUM7QUFDNUUsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLHVEQUF1RCxDQUFDOzs7QUFnQnBGLFFBQVEsQ0FBQztJQUNQLGtCQUFrQjtJQUNsQixhQUFhO0lBQ2IsV0FBVztJQUNYLHlCQUF5QjtJQUN6QixtQkFBbUI7Q0FDcEIsQ0FB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IElucHV0LCBPdXRwdXQsIEV2ZW50RW1pdHRlciwgT25Jbml0LCBPbkRlc3Ryb3ksIGluamVjdCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgQ29tbW9uTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uJztcbmltcG9ydCB7IEZvcm1zTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xuaW1wb3J0IHtcbiAgSW9uSWNvbixcbiAgSW9uQnV0dG9uLFxuICBJb25CYWRnZSxcbiAgSW9uVGV4dGFyZWEsXG4gIElvbkl0ZW0sXG4gIElvblNlbGVjdCxcbiAgSW9uU2VsZWN0T3B0aW9uLFxuICBJb25TcGlubmVyLFxuICBJb25JbmZpbml0ZVNjcm9sbCxcbiAgSW9uSW5maW5pdGVTY3JvbGxDb250ZW50LFxufSBmcm9tICdAaW9uaWMvYW5ndWxhci9zdGFuZGFsb25lJztcbmltcG9ydCB7IFN1YnNjcmlwdGlvbiB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgYWRkSWNvbnMgfSBmcm9tICdpb25pY29ucyc7XG5pbXBvcnQge1xuICBjaGF0YnViYmxlc091dGxpbmUsXG4gIGZpbHRlck91dGxpbmUsXG4gIHNlbmRPdXRsaW5lLFxuICBjaGF0YnViYmxlRWxsaXBzZXNPdXRsaW5lLFxuICBzd2FwVmVydGljYWxPdXRsaW5lLFxufSBmcm9tICdpb25pY29ucy9pY29ucyc7XG5cbmltcG9ydCB7IENvbW1lbnRDb21wb25lbnQgfSBmcm9tICcuLi8uLi9tb2xlY3VsZXMvY29tbWVudC9jb21tZW50LmNvbXBvbmVudCc7XG5pbXBvcnQgeyBBdmF0YXJDb21wb25lbnQgfSBmcm9tICcuLi8uLi9hdG9tcy9hdmF0YXIvYXZhdGFyLmNvbXBvbmVudCc7XG5pbXBvcnQgeyBTa2VsZXRvbkNvbXBvbmVudCB9IGZyb20gJy4uLy4uL2F0b21zL3NrZWxldG9uL3NrZWxldG9uLmNvbXBvbmVudCc7XG5pbXBvcnQgeyBMYW5nU2VydmljZSB9IGZyb20gJy4uLy4uLy4uL3NlcnZpY2VzL2xhbmctcHJvdmlkZXIvbGFuZy1wcm92aWRlci5zZXJ2aWNlJztcbmltcG9ydCB7XG4gIENvbW1lbnRTZWN0aW9uTWV0YWRhdGEsXG4gIENvbW1lbnRTb3J0T3B0aW9uLFxuICBDb21tZW50U29ydENoYW5nZUV2ZW50LFxuICBDb21tZW50U3VibWl0RXZlbnQsXG4gIENvbW1lbnRTZWN0aW9uTG9hZE1vcmVFdmVudCxcbn0gZnJvbSAnLi90eXBlcyc7XG5pbXBvcnQge1xuICBDb21tZW50QXV0aG9yQ2xpY2tFdmVudCxcbiAgQ29tbWVudFJlYWN0aW9uQ2xpY2tFdmVudCxcbiAgQ29tbWVudEFjdGlvbkNsaWNrRXZlbnQsXG4gIENvbW1lbnRNZW51SXRlbUNsaWNrRXZlbnQsXG4gIENvbW1lbnRMb2FkTW9yZUV2ZW50LFxufSBmcm9tICcuLi8uLi9tb2xlY3VsZXMvY29tbWVudC90eXBlcyc7XG5cbmFkZEljb25zKHtcbiAgY2hhdGJ1YmJsZXNPdXRsaW5lLFxuICBmaWx0ZXJPdXRsaW5lLFxuICBzZW5kT3V0bGluZSxcbiAgY2hhdGJ1YmJsZUVsbGlwc2VzT3V0bGluZSxcbiAgc3dhcFZlcnRpY2FsT3V0bGluZSxcbn0pO1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICd2YWwtY29tbWVudC1zZWN0aW9uJyxcbiAgc3RhbmRhbG9uZTogdHJ1ZSxcbiAgaW1wb3J0czogW1xuICAgIENvbW1vbk1vZHVsZSxcbiAgICBGb3Jtc01vZHVsZSxcbiAgICBJb25JY29uLFxuICAgIElvbkJ1dHRvbixcbiAgICBJb25CYWRnZSxcbiAgICBJb25UZXh0YXJlYSxcbiAgICBJb25JdGVtLFxuICAgIElvblNlbGVjdCxcbiAgICBJb25TZWxlY3RPcHRpb24sXG4gICAgSW9uU3Bpbm5lcixcbiAgICBJb25JbmZpbml0ZVNjcm9sbCxcbiAgICBJb25JbmZpbml0ZVNjcm9sbENvbnRlbnQsXG4gICAgQ29tbWVudENvbXBvbmVudCxcbiAgICBBdmF0YXJDb21wb25lbnQsXG4gICAgU2tlbGV0b25Db21wb25lbnQsXG4gIF0sXG4gIHRlbXBsYXRlOiBgXG4gICAgPGRpdiBjbGFzcz1cImNvbW1lbnQtc2VjdGlvblwiIFtjbGFzcy5sb2FkaW5nXT1cInByb3BzLmxvYWRpbmdcIj5cbiAgICAgIDwhLS0gSGVhZGVyIC0tPlxuICAgICAgPGRpdiBjbGFzcz1cInNlY3Rpb24taGVhZGVyXCI+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJoZWFkZXItdGl0bGVcIj5cbiAgICAgICAgICA8aW9uLWljb24gbmFtZT1cImNoYXRidWJibGVzLW91dGxpbmVcIiBjbGFzcz1cInRpdGxlLWljb25cIj48L2lvbi1pY29uPlxuICAgICAgICAgIDxoMyBjbGFzcz1cInRpdGxlXCI+e3sgZGlzcGxheVRpdGxlIH19PC9oMz5cbiAgICAgICAgICBAaWYgKHByb3BzLnNob3dDb3VudCAhPT0gZmFsc2UgJiYgcHJvcHMuY291bnQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgPGlvbi1iYWRnZSBjb2xvcj1cIm1lZGl1bVwiIGNsYXNzPVwiY291bnQtYmFkZ2VcIj5cbiAgICAgICAgICAgICAge3sgZm9ybWF0Q291bnQocHJvcHMuY291bnQpIH19XG4gICAgICAgICAgICA8L2lvbi1iYWRnZT5cbiAgICAgICAgICB9XG4gICAgICAgIDwvZGl2PlxuXG4gICAgICAgIEBpZiAocHJvcHMuc29ydE9wdGlvbnMgJiYgcHJvcHMuc29ydE9wdGlvbnMubGVuZ3RoID4gMCkge1xuICAgICAgICAgIDxkaXYgY2xhc3M9XCJoZWFkZXItYWN0aW9uc1wiPlxuICAgICAgICAgICAgPGlvbi1pdGVtIGxpbmVzPVwibm9uZVwiIGNsYXNzPVwic29ydC1zZWxlY3QtaXRlbVwiPlxuICAgICAgICAgICAgICA8aW9uLWljb24gbmFtZT1cInN3YXAtdmVydGljYWwtb3V0bGluZVwiIHNsb3Q9XCJzdGFydFwiIGNsYXNzPVwic29ydC1pY29uXCI+PC9pb24taWNvbj5cbiAgICAgICAgICAgICAgPGlvbi1zZWxlY3RcbiAgICAgICAgICAgICAgICBbdmFsdWVdPVwicHJvcHMuc2VsZWN0ZWRTb3J0XCJcbiAgICAgICAgICAgICAgICBbcGxhY2Vob2xkZXJdPVwicHJvcHMuc29ydExhYmVsIHx8ICdTb3J0IGJ5J1wiXG4gICAgICAgICAgICAgICAgaW50ZXJmYWNlPVwicG9wb3ZlclwiXG4gICAgICAgICAgICAgICAgKGlvbkNoYW5nZSk9XCJvblNvcnRDaGFuZ2UoJGV2ZW50KVwiXG4gICAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICBAZm9yIChvcHRpb24gb2YgcHJvcHMuc29ydE9wdGlvbnM7IHRyYWNrIG9wdGlvbi50b2tlbikge1xuICAgICAgICAgICAgICAgICAgPGlvbi1zZWxlY3Qtb3B0aW9uIFt2YWx1ZV09XCJvcHRpb24udG9rZW5cIj5cbiAgICAgICAgICAgICAgICAgICAge3sgZ2V0U29ydE9wdGlvbkxhYmVsKG9wdGlvbikgfX1cbiAgICAgICAgICAgICAgICAgIDwvaW9uLXNlbGVjdC1vcHRpb24+XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICA8L2lvbi1zZWxlY3Q+XG4gICAgICAgICAgICA8L2lvbi1pdGVtPlxuICAgICAgICAgIDwvZGl2PlxuICAgICAgICB9XG4gICAgICA8L2Rpdj5cblxuICAgICAgPCEtLSBOZXcgQ29tbWVudCBJbnB1dCAtLT5cbiAgICAgIEBpZiAocHJvcHMuc2hvd0lucHV0ICE9PSBmYWxzZSkge1xuICAgICAgICA8ZGl2IGNsYXNzPVwibmV3LWNvbW1lbnQtc2VjdGlvblwiPlxuICAgICAgICAgIDxkaXYgY2xhc3M9XCJpbnB1dC13cmFwcGVyXCI+XG4gICAgICAgICAgICBAaWYgKHByb3BzLmlucHV0Q29uZmlnPy5jdXJyZW50VXNlcj8uYXZhdGFyKSB7XG4gICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJpbnB1dC1hdmF0YXJcIj5cbiAgICAgICAgICAgICAgICA8dmFsLWF2YXRhciBbcHJvcHNdPVwicHJvcHMuaW5wdXRDb25maWcuY3VycmVudFVzZXIuYXZhdGFyXCI+PC92YWwtYXZhdGFyPlxuICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cImlucHV0LWNvbnRhaW5lclwiPlxuICAgICAgICAgICAgICA8aW9uLXRleHRhcmVhXG4gICAgICAgICAgICAgICAgWyhuZ01vZGVsKV09XCJuZXdDb21tZW50VGV4dFwiXG4gICAgICAgICAgICAgICAgW3BsYWNlaG9sZGVyXT1cImdldElucHV0UGxhY2Vob2xkZXIoKVwiXG4gICAgICAgICAgICAgICAgW21heGxlbmd0aF09XCJwcm9wcy5pbnB1dENvbmZpZz8ubWF4TGVuZ3RoIHx8IDIwMDBcIlxuICAgICAgICAgICAgICAgIFtkaXNhYmxlZF09XCJwcm9wcy5pbnB1dENvbmZpZz8uZGlzYWJsZWQgfHwgcHJvcHMubG9hZGluZ1wiXG4gICAgICAgICAgICAgICAgW2F1dG9Hcm93XT1cInRydWVcIlxuICAgICAgICAgICAgICAgIHJvd3M9XCIyXCJcbiAgICAgICAgICAgICAgICBjbGFzcz1cImNvbW1lbnQtdGV4dGFyZWFcIlxuICAgICAgICAgICAgICA+PC9pb24tdGV4dGFyZWE+XG5cbiAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImlucHV0LWFjdGlvbnNcIj5cbiAgICAgICAgICAgICAgICBAaWYgKHByb3BzLmlucHV0Q29uZmlnPy5zaG93Q291bnRlciAmJiBwcm9wcy5pbnB1dENvbmZpZz8ubWF4TGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICA8c3BhbiBjbGFzcz1cImNoYXItY291bnRlclwiIFtjbGFzcy53YXJuaW5nXT1cImlzTmVhckxpbWl0KClcIj5cbiAgICAgICAgICAgICAgICAgICAge3sgbmV3Q29tbWVudFRleHQubGVuZ3RoIH19IC8ge3sgcHJvcHMuaW5wdXRDb25maWcubWF4TGVuZ3RoIH19XG4gICAgICAgICAgICAgICAgICA8L3NwYW4+XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgPGlvbi1idXR0b25cbiAgICAgICAgICAgICAgICAgIFtjb2xvcl09XCJwcm9wcy5pbnB1dENvbmZpZz8uc3VibWl0Q29sb3IgfHwgcHJvcHMuY29sb3IgfHwgJ3ByaW1hcnknXCJcbiAgICAgICAgICAgICAgICAgIFtkaXNhYmxlZF09XCIhY2FuU3VibWl0KClcIlxuICAgICAgICAgICAgICAgICAgc2l6ZT1cInNtYWxsXCJcbiAgICAgICAgICAgICAgICAgIChjbGljayk9XCJvblN1Ym1pdENvbW1lbnQoKVwiXG4gICAgICAgICAgICAgICAgPlxuICAgICAgICAgICAgICAgICAgPGlvbi1pY29uIG5hbWU9XCJzZW5kLW91dGxpbmVcIiBzbG90PVwic3RhcnRcIj48L2lvbi1pY29uPlxuICAgICAgICAgICAgICAgICAge3sgZ2V0U3VibWl0TGFiZWwoKSB9fVxuICAgICAgICAgICAgICAgIDwvaW9uLWJ1dHRvbj5cbiAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgPC9kaXY+XG4gICAgICB9XG5cbiAgICAgIEBpZiAocHJvcHMubG9hZGluZykge1xuICAgICAgICA8ZGl2IGNsYXNzPVwibG9hZGluZy1zdGF0ZVwiPlxuICAgICAgICAgIEBmb3IgKGkgb2YgZ2V0U2tlbGV0b25BcnJheSgpOyB0cmFjayBpKSB7XG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwic2tlbGV0b24tY29tbWVudFwiPlxuICAgICAgICAgICAgICA8dmFsLXNrZWxldG9uIFtwcm9wc109XCJ7IHR5cGU6ICdhdmF0YXInLCB3aWR0aDogJzM2cHgnLCBoZWlnaHQ6ICczNnB4JyB9XCI+PC92YWwtc2tlbGV0b24+XG4gICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJza2VsZXRvbi1jb250ZW50XCI+XG4gICAgICAgICAgICAgICAgPHZhbC1za2VsZXRvbiBbcHJvcHNdPVwieyB0eXBlOiAndGV4dCcsIHdpZHRoOiAnMTIwcHgnLCBoZWlnaHQ6ICcxNHB4JyB9XCI+PC92YWwtc2tlbGV0b24+XG4gICAgICAgICAgICAgICAgPHZhbC1za2VsZXRvbiBbcHJvcHNdPVwieyB0eXBlOiAncGFyYWdyYXBoJywgbGluZXM6IDIgfVwiPjwvdmFsLXNrZWxldG9uPlxuICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgIH1cbiAgICAgICAgPC9kaXY+XG4gICAgICB9IEBlbHNlIGlmIChwcm9wcy5jb21tZW50cyAmJiBwcm9wcy5jb21tZW50cy5sZW5ndGggPiAwKSB7XG4gICAgICAgIDxkaXYgY2xhc3M9XCJjb21tZW50cy1saXN0XCIgW2NsYXNzLndpdGgtZGl2aWRlcnNdPVwicHJvcHMuc2hvd0RpdmlkZXJzXCI+XG4gICAgICAgICAgQGZvciAoY29tbWVudCBvZiBwcm9wcy5jb21tZW50czsgdHJhY2sgY29tbWVudC50b2tlbikge1xuICAgICAgICAgICAgPHZhbC1jb21tZW50XG4gICAgICAgICAgICAgIFtwcm9wc109XCJjb21tZW50XCJcbiAgICAgICAgICAgICAgKGF1dGhvckNsaWNrKT1cImF1dGhvckNsaWNrLmVtaXQoJGV2ZW50KVwiXG4gICAgICAgICAgICAgIChyZWFjdGlvbkNsaWNrKT1cInJlYWN0aW9uQ2xpY2suZW1pdCgkZXZlbnQpXCJcbiAgICAgICAgICAgICAgKGFjdGlvbkNsaWNrKT1cIm9uQ29tbWVudEFjdGlvbigkZXZlbnQpXCJcbiAgICAgICAgICAgICAgKG1lbnVJdGVtQ2xpY2spPVwibWVudUl0ZW1DbGljay5lbWl0KCRldmVudClcIlxuICAgICAgICAgICAgICAobG9hZE1vcmVDbGljayk9XCJjb21tZW50TG9hZE1vcmUuZW1pdCgkZXZlbnQpXCJcbiAgICAgICAgICAgICAgKGNvbGxhcHNlVG9nZ2xlKT1cImNvbGxhcHNlVG9nZ2xlLmVtaXQoJGV2ZW50KVwiXG4gICAgICAgICAgICA+PC92YWwtY29tbWVudD5cblxuICAgICAgICAgICAgQGlmIChwcm9wcy5zaG93RGl2aWRlcnMgJiYgISRsYXN0KSB7XG4gICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJjb21tZW50LWRpdmlkZXJcIj48L2Rpdj5cbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG5cbiAgICAgICAgICBAaWYgKHByb3BzLmhhc01vcmUgJiYgcHJvcHMucGFnaW5hdGlvbk1vZGUgIT09ICdpbmZpbml0ZScpIHtcbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJsb2FkLW1vcmUtc2VjdGlvblwiPlxuICAgICAgICAgICAgICBAaWYgKHByb3BzLmxvYWRpbmdNb3JlKSB7XG4gICAgICAgICAgICAgICAgPGlvbi1zcGlubmVyIG5hbWU9XCJjcmVzY2VudFwiIFtjb2xvcl09XCJwcm9wcy5jb2xvciB8fCAncHJpbWFyeSdcIj48L2lvbi1zcGlubmVyPlxuICAgICAgICAgICAgICB9IEBlbHNlIHtcbiAgICAgICAgICAgICAgICA8aW9uLWJ1dHRvblxuICAgICAgICAgICAgICAgICAgZmlsbD1cIm91dGxpbmVcIlxuICAgICAgICAgICAgICAgICAgW2NvbG9yXT1cInByb3BzLmNvbG9yIHx8ICdwcmltYXJ5J1wiXG4gICAgICAgICAgICAgICAgICBleHBhbmQ9XCJibG9ja1wiXG4gICAgICAgICAgICAgICAgICAoY2xpY2spPVwib25Mb2FkTW9yZSgpXCJcbiAgICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgICB7eyBkaXNwbGF5TG9hZE1vcmVMYWJlbCB9fVxuICAgICAgICAgICAgICAgIDwvaW9uLWJ1dHRvbj5cbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgfVxuICAgICAgICA8L2Rpdj5cblxuICAgICAgICBAaWYgKHByb3BzLnBhZ2luYXRpb25Nb2RlID09PSAnaW5maW5pdGUnKSB7XG4gICAgICAgICAgPGlvbi1pbmZpbml0ZS1zY3JvbGxcbiAgICAgICAgICAgIFt0aHJlc2hvbGRdPVwicHJvcHMuaW5maW5pdGVTY3JvbGxUaHJlc2hvbGQgfHwgJzEwMHB4J1wiXG4gICAgICAgICAgICBbcG9zaXRpb25dPVwicHJvcHMuaW5maW5pdGVTY3JvbGxQb3NpdGlvbiB8fCAnYm90dG9tJ1wiXG4gICAgICAgICAgICBbZGlzYWJsZWRdPVwiIXByb3BzLmhhc01vcmVcIlxuICAgICAgICAgICAgKGlvbkluZmluaXRlKT1cIm9uSW5maW5pdGVTY3JvbGwoJGV2ZW50KVwiXG4gICAgICAgICAgPlxuICAgICAgICAgICAgPGlvbi1pbmZpbml0ZS1zY3JvbGwtY29udGVudFxuICAgICAgICAgICAgICBbbG9hZGluZ1NwaW5uZXJdPVwiJ2NyZXNjZW50J1wiXG4gICAgICAgICAgICAgIFtsb2FkaW5nVGV4dF09XCJkaXNwbGF5TG9hZE1vcmVMYWJlbFwiXG4gICAgICAgICAgICA+PC9pb24taW5maW5pdGUtc2Nyb2xsLWNvbnRlbnQ+XG4gICAgICAgICAgPC9pb24taW5maW5pdGUtc2Nyb2xsPlxuICAgICAgICB9XG4gICAgICB9IEBlbHNlIHtcbiAgICAgICAgPGRpdiBjbGFzcz1cImVtcHR5LXN0YXRlXCI+XG4gICAgICAgICAgPGlvbi1pY29uXG4gICAgICAgICAgICBbbmFtZV09XCJwcm9wcy5lbXB0eVN0YXRlPy5pY29uIHx8ICdjaGF0YnViYmxlLWVsbGlwc2VzLW91dGxpbmUnXCJcbiAgICAgICAgICAgIGNsYXNzPVwiZW1wdHktaWNvblwiXG4gICAgICAgICAgPjwvaW9uLWljb24+XG4gICAgICAgICAgPGg0IGNsYXNzPVwiZW1wdHktdGl0bGVcIj57eyBnZXRFbXB0eVRpdGxlKCkgfX08L2g0PlxuICAgICAgICAgIDxwIGNsYXNzPVwiZW1wdHktbWVzc2FnZVwiPnt7IGdldEVtcHR5TWVzc2FnZSgpIH19PC9wPlxuICAgICAgICA8L2Rpdj5cbiAgICAgIH1cbiAgICA8L2Rpdj5cbiAgYCxcbiAgc3R5bGVVcmxzOiBbJy4vY29tbWVudC1zZWN0aW9uLmNvbXBvbmVudC5zY3NzJ10sXG59KVxuLyoqXG4gKiB2YWwtY29tbWVudC1zZWN0aW9uXG4gKlxuICogQW4gb3JnYW5pc20gY29tcG9uZW50IHRoYXQgcHJvdmlkZXMgYSBjb21wbGV0ZSBjb21tZW50IHNlY3Rpb24gd2l0aDpcbiAqIC0gSGVhZGVyIHdpdGggdGl0bGUgYW5kIGNvdW50XG4gKiAtIFNvcnQvZmlsdGVyIG9wdGlvbnNcbiAqIC0gTmV3IGNvbW1lbnQgaW5wdXRcbiAqIC0gQ29tbWVudHMgbGlzdCB3aXRoIHZhbC1jb21tZW50XG4gKiAtIExvYWQgbW9yZSBwYWdpbmF0aW9uXG4gKiAtIEVtcHR5IHN0YXRlXG4gKlxuICogQGV4YW1wbGUgQmFzaWMgdXNhZ2VcbiAqIDx2YWwtY29tbWVudC1zZWN0aW9uIFtwcm9wc109XCJ7XG4gKiAgIHRpdGxlOiAnQ29tbWVudHMnLFxuICogICBjb3VudDogNDIsXG4gKiAgIGNvbW1lbnRzOiBjb21tZW50c0FycmF5LFxuICogICBzaG93SW5wdXQ6IHRydWVcbiAqIH1cIj48L3ZhbC1jb21tZW50LXNlY3Rpb24+XG4gKlxuICogQGV4YW1wbGUgV2l0aCBzb3J0aW5nXG4gKiA8dmFsLWNvbW1lbnQtc2VjdGlvbiBbcHJvcHNdPVwie1xuICogICB0aXRsZTogJ1Jldmlld3MnLFxuICogICBjb3VudDogMTI4LFxuICogICBjb21tZW50czogcmV2aWV3cyxcbiAqICAgc29ydE9wdGlvbnM6IFtcbiAqICAgICB7IHRva2VuOiAnbmV3ZXN0JywgbGFiZWw6ICdOZXdlc3QgZmlyc3QnIH0sXG4gKiAgICAgeyB0b2tlbjogJ29sZGVzdCcsIGxhYmVsOiAnT2xkZXN0IGZpcnN0JyB9LFxuICogICAgIHsgdG9rZW46ICdwb3B1bGFyJywgbGFiZWw6ICdNb3N0IHBvcHVsYXInIH1cbiAqICAgXSxcbiAqICAgc2VsZWN0ZWRTb3J0OiAnbmV3ZXN0J1xuICogfVwiIChzb3J0Q2hhbmdlKT1cIm9uU29ydCgkZXZlbnQpXCI+PC92YWwtY29tbWVudC1zZWN0aW9uPlxuICpcbiAqIEBpbnB1dCBwcm9wczogQ29tbWVudFNlY3Rpb25NZXRhZGF0YSAtIENvbmZpZ3VyYXRpb24gZm9yIHRoZSBzZWN0aW9uXG4gKiBAb3V0cHV0IHNvcnRDaGFuZ2UgLSBTb3J0IG9wdGlvbiBjaGFuZ2VkXG4gKiBAb3V0cHV0IGNvbW1lbnRTdWJtaXQgLSBOZXcgY29tbWVudCBzdWJtaXR0ZWRcbiAqIEBvdXRwdXQgbG9hZE1vcmUgLSBMb2FkIG1vcmUgY2xpY2tlZFxuICogQG91dHB1dCBhdXRob3JDbGljayAtIENvbW1lbnQgYXV0aG9yIGNsaWNrZWQgKGJ1YmJsZWQgZnJvbSB2YWwtY29tbWVudClcbiAqIEBvdXRwdXQgcmVhY3Rpb25DbGljayAtIFJlYWN0aW9uIGNsaWNrZWQgKGJ1YmJsZWQpXG4gKiBAb3V0cHV0IGFjdGlvbkNsaWNrIC0gQWN0aW9uIGNsaWNrZWQgKGJ1YmJsZWQpXG4gKiBAb3V0cHV0IG1lbnVJdGVtQ2xpY2sgLSBNZW51IGl0ZW0gY2xpY2tlZCAoYnViYmxlZClcbiAqIEBvdXRwdXQgY29tbWVudExvYWRNb3JlIC0gTG9hZCBtb3JlIHJlcGxpZXMgY2xpY2tlZCAoYnViYmxlZClcbiAqIEBvdXRwdXQgY29sbGFwc2VUb2dnbGUgLSBDb21tZW50IGNvbGxhcHNlIHRvZ2dsZWQgKGJ1YmJsZWQpXG4gKi9cbmV4cG9ydCBjbGFzcyBDb21tZW50U2VjdGlvbkNvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCwgT25EZXN0cm95IHtcbiAgQElucHV0KCkgcHJvcHM6IENvbW1lbnRTZWN0aW9uTWV0YWRhdGE7XG5cbiAgLy8gU2VjdGlvbiBldmVudHNcbiAgQE91dHB1dCgpIHNvcnRDaGFuZ2UgPSBuZXcgRXZlbnRFbWl0dGVyPENvbW1lbnRTb3J0Q2hhbmdlRXZlbnQ+KCk7XG4gIEBPdXRwdXQoKSBjb21tZW50U3VibWl0ID0gbmV3IEV2ZW50RW1pdHRlcjxDb21tZW50U3VibWl0RXZlbnQ+KCk7XG4gIEBPdXRwdXQoKSBsb2FkTW9yZSA9IG5ldyBFdmVudEVtaXR0ZXI8Q29tbWVudFNlY3Rpb25Mb2FkTW9yZUV2ZW50PigpO1xuXG4gIC8vIEJ1YmJsZWQgZXZlbnRzIGZyb20gdmFsLWNvbW1lbnRcbiAgQE91dHB1dCgpIGF1dGhvckNsaWNrID0gbmV3IEV2ZW50RW1pdHRlcjxDb21tZW50QXV0aG9yQ2xpY2tFdmVudD4oKTtcbiAgQE91dHB1dCgpIHJlYWN0aW9uQ2xpY2sgPSBuZXcgRXZlbnRFbWl0dGVyPENvbW1lbnRSZWFjdGlvbkNsaWNrRXZlbnQ+KCk7XG4gIEBPdXRwdXQoKSBhY3Rpb25DbGljayA9IG5ldyBFdmVudEVtaXR0ZXI8Q29tbWVudEFjdGlvbkNsaWNrRXZlbnQ+KCk7XG4gIEBPdXRwdXQoKSBtZW51SXRlbUNsaWNrID0gbmV3IEV2ZW50RW1pdHRlcjxDb21tZW50TWVudUl0ZW1DbGlja0V2ZW50PigpO1xuICBAT3V0cHV0KCkgY29tbWVudExvYWRNb3JlID0gbmV3IEV2ZW50RW1pdHRlcjxDb21tZW50TG9hZE1vcmVFdmVudD4oKTtcbiAgQE91dHB1dCgpIGNvbGxhcHNlVG9nZ2xlID0gbmV3IEV2ZW50RW1pdHRlcjx7IHRva2VuOiBzdHJpbmc7IGNvbGxhcHNlZDogYm9vbGVhbiB9PigpO1xuXG4gIC8vIFJlcGx5IHN0YXRlXG4gIEBPdXRwdXQoKSByZXBseVN0YXJ0ID0gbmV3IEV2ZW50RW1pdHRlcjx7IGNvbW1lbnRUb2tlbjogc3RyaW5nIH0+KCk7XG5cbiAgbmV3Q29tbWVudFRleHQgPSAnJztcbiAgcmVwbHlpbmdUbzogc3RyaW5nIHwgbnVsbCA9IG51bGw7XG5cbiAgZGlzcGxheVRpdGxlID0gJyc7XG4gIGRpc3BsYXlMb2FkTW9yZUxhYmVsID0gJyc7XG5cbiAgcHJpdmF0ZSBsYW5nU3Vic2NyaXB0aW9uOiBTdWJzY3JpcHRpb24gfCBudWxsID0gbnVsbDtcbiAgcHJpdmF0ZSBsYW5nU2VydmljZSA9IGluamVjdChMYW5nU2VydmljZSk7XG5cbiAgbmdPbkluaXQoKTogdm9pZCB7XG4gICAgdGhpcy51cGRhdGVEaXNwbGF5VGV4dHMoKTtcblxuICAgIGlmICh0aGlzLmhhc1JlYWN0aXZlQ29udGVudCgpKSB7XG4gICAgICB0aGlzLmxhbmdTdWJzY3JpcHRpb24gPSB0aGlzLmxhbmdTZXJ2aWNlLmN1cnJlbnRMYW5nJC5zdWJzY3JpYmUoKCkgPT4ge1xuICAgICAgICB0aGlzLnVwZGF0ZURpc3BsYXlUZXh0cygpO1xuICAgICAgfSk7XG4gICAgfVxuICB9XG5cbiAgbmdPbkRlc3Ryb3koKTogdm9pZCB7XG4gICAgdGhpcy5sYW5nU3Vic2NyaXB0aW9uPy51bnN1YnNjcmliZSgpO1xuICB9XG5cbiAgcHJpdmF0ZSBoYXNSZWFjdGl2ZUNvbnRlbnQoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuICEhKFxuICAgICAgKHRoaXMucHJvcHMudGl0bGVDb250ZW50S2V5ICYmIHRoaXMucHJvcHMuY29udGVudENsYXNzKSB8fFxuICAgICAgKHRoaXMucHJvcHMubG9hZE1vcmVDb250ZW50S2V5ICYmIHRoaXMucHJvcHMuY29udGVudENsYXNzKVxuICAgICk7XG4gIH1cblxuICBwcml2YXRlIHVwZGF0ZURpc3BsYXlUZXh0cygpOiB2b2lkIHtcbiAgICAvLyBUaXRsZVxuICAgIGlmICh0aGlzLnByb3BzLnRpdGxlQ29udGVudEtleSAmJiB0aGlzLnByb3BzLmNvbnRlbnRDbGFzcykge1xuICAgICAgdGhpcy5kaXNwbGF5VGl0bGUgPSB0aGlzLmxhbmdTZXJ2aWNlLmdldFRleHQoXG4gICAgICAgIHRoaXMucHJvcHMuY29udGVudENsYXNzLFxuICAgICAgICB0aGlzLnByb3BzLnRpdGxlQ29udGVudEtleSxcbiAgICAgICAgdGhpcy5wcm9wcy50aXRsZUNvbnRlbnRGYWxsYmFjayB8fCB0aGlzLnByb3BzLnRpdGxlIHx8ICdDb21tZW50cydcbiAgICAgICk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuZGlzcGxheVRpdGxlID0gdGhpcy5wcm9wcy50aXRsZSB8fCAnQ29tbWVudHMnO1xuICAgIH1cblxuICAgIC8vIExvYWQgbW9yZSBsYWJlbFxuICAgIGlmICh0aGlzLnByb3BzLmxvYWRNb3JlQ29udGVudEtleSAmJiB0aGlzLnByb3BzLmNvbnRlbnRDbGFzcykge1xuICAgICAgdGhpcy5kaXNwbGF5TG9hZE1vcmVMYWJlbCA9IHRoaXMubGFuZ1NlcnZpY2UuZ2V0VGV4dChcbiAgICAgICAgdGhpcy5wcm9wcy5jb250ZW50Q2xhc3MsXG4gICAgICAgIHRoaXMucHJvcHMubG9hZE1vcmVDb250ZW50S2V5LFxuICAgICAgICB0aGlzLnByb3BzLmxvYWRNb3JlTGFiZWwgfHwgJ0xvYWQgbW9yZSBjb21tZW50cydcbiAgICAgICk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuZGlzcGxheUxvYWRNb3JlTGFiZWwgPSB0aGlzLnByb3BzLmxvYWRNb3JlTGFiZWwgfHwgJ0xvYWQgbW9yZSBjb21tZW50cyc7XG4gICAgfVxuICB9XG5cbiAgZm9ybWF0Q291bnQoY291bnQ6IG51bWJlcik6IHN0cmluZyB7XG4gICAgaWYgKGNvdW50ID49IDEwMDAwMDApIHtcbiAgICAgIHJldHVybiAoY291bnQgLyAxMDAwMDAwKS50b0ZpeGVkKDEpLnJlcGxhY2UoL1xcLjAkLywgJycpICsgJ00nO1xuICAgIH1cbiAgICBpZiAoY291bnQgPj0gMTAwMCkge1xuICAgICAgcmV0dXJuIChjb3VudCAvIDEwMDApLnRvRml4ZWQoMSkucmVwbGFjZSgvXFwuMCQvLCAnJykgKyAnSyc7XG4gICAgfVxuICAgIHJldHVybiBjb3VudC50b1N0cmluZygpO1xuICB9XG5cbiAgZ2V0U29ydE9wdGlvbkxhYmVsKG9wdGlvbjogQ29tbWVudFNvcnRPcHRpb24pOiBzdHJpbmcge1xuICAgIGlmIChvcHRpb24uY29udGVudEtleSAmJiBvcHRpb24uY29udGVudENsYXNzKSB7XG4gICAgICByZXR1cm4gdGhpcy5sYW5nU2VydmljZS5nZXRUZXh0KFxuICAgICAgICBvcHRpb24uY29udGVudENsYXNzLFxuICAgICAgICBvcHRpb24uY29udGVudEtleSxcbiAgICAgICAgb3B0aW9uLmNvbnRlbnRGYWxsYmFjayB8fCBvcHRpb24ubGFiZWxcbiAgICAgICk7XG4gICAgfVxuICAgIHJldHVybiBvcHRpb24ubGFiZWw7XG4gIH1cblxuICBnZXRJbnB1dFBsYWNlaG9sZGVyKCk6IHN0cmluZyB7XG4gICAgY29uc3QgY29uZmlnID0gdGhpcy5wcm9wcy5pbnB1dENvbmZpZztcbiAgICBpZiAoY29uZmlnPy5wbGFjZWhvbGRlckNvbnRlbnRLZXkgJiYgY29uZmlnPy5jb250ZW50Q2xhc3MpIHtcbiAgICAgIHJldHVybiB0aGlzLmxhbmdTZXJ2aWNlLmdldFRleHQoXG4gICAgICAgIGNvbmZpZy5jb250ZW50Q2xhc3MsXG4gICAgICAgIGNvbmZpZy5wbGFjZWhvbGRlckNvbnRlbnRLZXksXG4gICAgICAgIGNvbmZpZy5wbGFjZWhvbGRlciB8fCAnV3JpdGUgYSBjb21tZW50Li4uJ1xuICAgICAgKTtcbiAgICB9XG4gICAgcmV0dXJuIGNvbmZpZz8ucGxhY2Vob2xkZXIgfHwgJ1dyaXRlIGEgY29tbWVudC4uLic7XG4gIH1cblxuICBnZXRTdWJtaXRMYWJlbCgpOiBzdHJpbmcge1xuICAgIGNvbnN0IGNvbmZpZyA9IHRoaXMucHJvcHMuaW5wdXRDb25maWc7XG4gICAgaWYgKGNvbmZpZz8uc3VibWl0TGFiZWxDb250ZW50S2V5ICYmIGNvbmZpZz8uY29udGVudENsYXNzKSB7XG4gICAgICByZXR1cm4gdGhpcy5sYW5nU2VydmljZS5nZXRUZXh0KFxuICAgICAgICBjb25maWcuY29udGVudENsYXNzLFxuICAgICAgICBjb25maWcuc3VibWl0TGFiZWxDb250ZW50S2V5LFxuICAgICAgICBjb25maWcuc3VibWl0TGFiZWwgfHwgJ1Bvc3QnXG4gICAgICApO1xuICAgIH1cbiAgICByZXR1cm4gY29uZmlnPy5zdWJtaXRMYWJlbCB8fCAnUG9zdCc7XG4gIH1cblxuICBnZXRFbXB0eVRpdGxlKCk6IHN0cmluZyB7XG4gICAgY29uc3QgZW1wdHkgPSB0aGlzLnByb3BzLmVtcHR5U3RhdGU7XG4gICAgaWYgKGVtcHR5Py50aXRsZUNvbnRlbnRLZXkgJiYgZW1wdHk/LmNvbnRlbnRDbGFzcykge1xuICAgICAgcmV0dXJuIHRoaXMubGFuZ1NlcnZpY2UuZ2V0VGV4dChcbiAgICAgICAgZW1wdHkuY29udGVudENsYXNzLFxuICAgICAgICBlbXB0eS50aXRsZUNvbnRlbnRLZXksXG4gICAgICAgIGVtcHR5LnRpdGxlIHx8ICdObyBjb21tZW50cyB5ZXQnXG4gICAgICApO1xuICAgIH1cbiAgICByZXR1cm4gZW1wdHk/LnRpdGxlIHx8ICdObyBjb21tZW50cyB5ZXQnO1xuICB9XG5cbiAgZ2V0RW1wdHlNZXNzYWdlKCk6IHN0cmluZyB7XG4gICAgY29uc3QgZW1wdHkgPSB0aGlzLnByb3BzLmVtcHR5U3RhdGU7XG4gICAgaWYgKGVtcHR5Py5tZXNzYWdlQ29udGVudEtleSAmJiBlbXB0eT8uY29udGVudENsYXNzKSB7XG4gICAgICByZXR1cm4gdGhpcy5sYW5nU2VydmljZS5nZXRUZXh0KFxuICAgICAgICBlbXB0eS5jb250ZW50Q2xhc3MsXG4gICAgICAgIGVtcHR5Lm1lc3NhZ2VDb250ZW50S2V5LFxuICAgICAgICBlbXB0eS5tZXNzYWdlIHx8ICdCZSB0aGUgZmlyc3QgdG8gc2hhcmUgeW91ciB0aG91Z2h0cyEnXG4gICAgICApO1xuICAgIH1cbiAgICByZXR1cm4gZW1wdHk/Lm1lc3NhZ2UgfHwgJ0JlIHRoZSBmaXJzdCB0byBzaGFyZSB5b3VyIHRob3VnaHRzISc7XG4gIH1cblxuICBnZXRTa2VsZXRvbkFycmF5KCk6IG51bWJlcltdIHtcbiAgICBjb25zdCBjb3VudCA9IHRoaXMucHJvcHMuc2tlbGV0b25Db3VudCB8fCAzO1xuICAgIHJldHVybiBBcnJheShjb3VudCkuZmlsbCgwKS5tYXAoKF8sIGkpID0+IGkpO1xuICB9XG5cbiAgY2FuU3VibWl0KCk6IGJvb2xlYW4ge1xuICAgIGNvbnN0IG1pbkxlbmd0aCA9IHRoaXMucHJvcHMuaW5wdXRDb25maWc/Lm1pbkxlbmd0aCB8fCAxO1xuICAgIHJldHVybiAoXG4gICAgICB0aGlzLm5ld0NvbW1lbnRUZXh0LnRyaW0oKS5sZW5ndGggPj0gbWluTGVuZ3RoICYmXG4gICAgICAhdGhpcy5wcm9wcy5sb2FkaW5nICYmXG4gICAgICAhdGhpcy5wcm9wcy5pbnB1dENvbmZpZz8uZGlzYWJsZWRcbiAgICApO1xuICB9XG5cbiAgaXNOZWFyTGltaXQoKTogYm9vbGVhbiB7XG4gICAgY29uc3QgbWF4TGVuZ3RoID0gdGhpcy5wcm9wcy5pbnB1dENvbmZpZz8ubWF4TGVuZ3RoIHx8IDIwMDA7XG4gICAgcmV0dXJuIHRoaXMubmV3Q29tbWVudFRleHQubGVuZ3RoID4gbWF4TGVuZ3RoICogMC45O1xuICB9XG5cbiAgb25Tb3J0Q2hhbmdlKGV2ZW50OiBDdXN0b21FdmVudCk6IHZvaWQge1xuICAgIGNvbnN0IHNlbGVjdGVkVG9rZW4gPSBldmVudC5kZXRhaWwudmFsdWU7XG4gICAgY29uc3Qgb3B0aW9uID0gdGhpcy5wcm9wcy5zb3J0T3B0aW9ucz8uZmluZCgobykgPT4gby50b2tlbiA9PT0gc2VsZWN0ZWRUb2tlbik7XG5cbiAgICBpZiAob3B0aW9uKSB7XG4gICAgICB0aGlzLnNvcnRDaGFuZ2UuZW1pdCh7XG4gICAgICAgIG9wdGlvbixcbiAgICAgICAgcHJldmlvdXNTb3J0OiB0aGlzLnByb3BzLnNlbGVjdGVkU29ydCxcbiAgICAgIH0pO1xuICAgIH1cbiAgfVxuXG4gIG9uU3VibWl0Q29tbWVudCgpOiB2b2lkIHtcbiAgICBpZiAoIXRoaXMuY2FuU3VibWl0KCkpIHJldHVybjtcblxuICAgIHRoaXMuY29tbWVudFN1Ym1pdC5lbWl0KHtcbiAgICAgIGNvbnRlbnQ6IHRoaXMubmV3Q29tbWVudFRleHQudHJpbSgpLFxuICAgICAgcGFyZW50VG9rZW46IHRoaXMucmVwbHlpbmdUbyB8fCB1bmRlZmluZWQsXG4gICAgICBzZWN0aW9uVG9rZW46IHRoaXMucHJvcHMudG9rZW4sXG4gICAgfSk7XG5cbiAgICB0aGlzLm5ld0NvbW1lbnRUZXh0ID0gJyc7XG4gICAgdGhpcy5yZXBseWluZ1RvID0gbnVsbDtcbiAgfVxuXG4gIG9uQ29tbWVudEFjdGlvbihldmVudDogQ29tbWVudEFjdGlvbkNsaWNrRXZlbnQpOiB2b2lkIHtcbiAgICAvLyBDaGVjayBpZiBpdCdzIGEgcmVwbHkgYWN0aW9uXG4gICAgaWYgKGV2ZW50LmFjdGlvbi50b2tlbiA9PT0gJ3JlcGx5Jykge1xuICAgICAgdGhpcy5yZXBseWluZ1RvID0gZXZlbnQuY29tbWVudFRva2VuO1xuICAgICAgdGhpcy5yZXBseVN0YXJ0LmVtaXQoeyBjb21tZW50VG9rZW46IGV2ZW50LmNvbW1lbnRUb2tlbiB9KTtcbiAgICB9XG5cbiAgICB0aGlzLmFjdGlvbkNsaWNrLmVtaXQoZXZlbnQpO1xuICB9XG5cbiAgb25Mb2FkTW9yZSgpOiB2b2lkIHtcbiAgICB0aGlzLmxvYWRNb3JlLmVtaXQoe1xuICAgICAgc2VjdGlvblRva2VuOiB0aGlzLnByb3BzLnRva2VuLFxuICAgICAgY3VycmVudENvdW50OiB0aGlzLnByb3BzLmNvbW1lbnRzPy5sZW5ndGggfHwgMCxcbiAgICB9KTtcbiAgfVxuXG4gIG9uSW5maW5pdGVTY3JvbGwoZXZlbnQ6IEN1c3RvbUV2ZW50KTogdm9pZCB7XG4gICAgdGhpcy5sb2FkTW9yZS5lbWl0KHtcbiAgICAgIHNlY3Rpb25Ub2tlbjogdGhpcy5wcm9wcy50b2tlbixcbiAgICAgIGN1cnJlbnRDb3VudDogdGhpcy5wcm9wcy5jb21tZW50cz8ubGVuZ3RoIHx8IDAsXG4gICAgfSk7XG5cbiAgICAvLyBUaGUgcGFyZW50IGNvbXBvbmVudCBzaG91bGQgY2FsbCBjb21wbGV0ZUluZmluaXRlU2Nyb2xsKCkgd2hlbiBkb25lIGxvYWRpbmdcbiAgICAvLyBTdG9yZSByZWZlcmVuY2UgdG8gY29tcGxldGUgdGhlIGluZmluaXRlIHNjcm9sbFxuICAgIHRoaXMuaW5maW5pdGVTY3JvbGxFdmVudCA9IGV2ZW50O1xuICB9XG5cbiAgLy8gQ2FsbCB0aGlzIG1ldGhvZCBmcm9tIHBhcmVudCBhZnRlciBsb2FkaW5nIG1vcmUgY29tbWVudHNcbiAgY29tcGxldGVJbmZpbml0ZVNjcm9sbCgpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5pbmZpbml0ZVNjcm9sbEV2ZW50KSB7XG4gICAgICAodGhpcy5pbmZpbml0ZVNjcm9sbEV2ZW50LnRhcmdldCBhcyBIVE1MSW9uSW5maW5pdGVTY3JvbGxFbGVtZW50KS5jb21wbGV0ZSgpO1xuICAgICAgdGhpcy5pbmZpbml0ZVNjcm9sbEV2ZW50ID0gbnVsbDtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGluZmluaXRlU2Nyb2xsRXZlbnQ6IEN1c3RvbUV2ZW50IHwgbnVsbCA9IG51bGw7XG5cbiAgLy8gTWV0aG9kIHRvIHByb2dyYW1tYXRpY2FsbHkgc3RhcnQgYSByZXBseVxuICBzdGFydFJlcGx5KGNvbW1lbnRUb2tlbjogc3RyaW5nKTogdm9pZCB7XG4gICAgdGhpcy5yZXBseWluZ1RvID0gY29tbWVudFRva2VuO1xuICB9XG5cbiAgLy8gTWV0aG9kIHRvIGNhbmNlbCByZXBseVxuICBjYW5jZWxSZXBseSgpOiB2b2lkIHtcbiAgICB0aGlzLnJlcGx5aW5nVG8gPSBudWxsO1xuICB9XG59XG4iXX0=
|