@acorex/modules 21.0.0-next.59 → 21.0.0-next.64
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/assessment-management/README.md +4 -4
- package/fesm2022/{acorex-modules-assessment-management-acorex-modules-assessment-management-o8aFazwA.mjs → acorex-modules-assessment-management-acorex-modules-assessment-management-DqmJVJ0z.mjs} +3599 -373
- package/fesm2022/acorex-modules-assessment-management-acorex-modules-assessment-management-DqmJVJ0z.mjs.map +1 -0
- package/fesm2022/{acorex-modules-assessment-management-assessment-case.entity-yrc_Yybq.mjs → acorex-modules-assessment-management-assessment-case.entity-DhVwPz0T.mjs} +45 -29
- package/fesm2022/acorex-modules-assessment-management-assessment-case.entity-DhVwPz0T.mjs.map +1 -0
- package/fesm2022/{acorex-modules-assessment-management-assessment-session.entity-Cwf30iuu.mjs → acorex-modules-assessment-management-assessment-session.entity-BvV2Qgw1.mjs} +19 -3
- package/fesm2022/acorex-modules-assessment-management-assessment-session.entity-BvV2Qgw1.mjs.map +1 -0
- package/fesm2022/{acorex-modules-assessment-management-fill-assessment-session.command-CJieLR5g.mjs → acorex-modules-assessment-management-fill-assessment-session.command-4fkaeAG-.mjs} +2 -2
- package/fesm2022/acorex-modules-assessment-management-fill-assessment-session.command-4fkaeAG-.mjs.map +1 -0
- package/fesm2022/{acorex-modules-assessment-management-preview-question.command-D0-FB1HH.mjs → acorex-modules-assessment-management-preview-question.command-6IGOdVVZ.mjs} +2 -2
- package/fesm2022/acorex-modules-assessment-management-preview-question.command-6IGOdVVZ.mjs.map +1 -0
- package/fesm2022/{acorex-modules-assessment-management-preview-questionnaire.command-wqPNgv7q.mjs → acorex-modules-assessment-management-preview-questionnaire.command-CRDBe_BS.mjs} +2 -2
- package/fesm2022/{acorex-modules-assessment-management-preview-questionnaire.command-wqPNgv7q.mjs.map → acorex-modules-assessment-management-preview-questionnaire.command-CRDBe_BS.mjs.map} +1 -1
- package/fesm2022/{acorex-modules-assessment-management-question-bank-interface-editor-widget-edit.component-DYyUhSWd.mjs → acorex-modules-assessment-management-question-bank-interface-editor-widget-edit.component-B2ES-zcL.mjs} +2 -2
- package/fesm2022/acorex-modules-assessment-management-question-bank-interface-editor-widget-edit.component-B2ES-zcL.mjs.map +1 -0
- package/fesm2022/{acorex-modules-assessment-management-question-bank-item.entity-DUf2ceKY.mjs → acorex-modules-assessment-management-question-bank-item.entity-Cw2WCdYK.mjs} +2 -2
- package/fesm2022/{acorex-modules-assessment-management-question-bank-item.entity-DUf2ceKY.mjs.map → acorex-modules-assessment-management-question-bank-item.entity-Cw2WCdYK.mjs.map} +1 -1
- package/fesm2022/{acorex-modules-assessment-management-questionnaire-viewer-popup.component-Cy5ElBmU.mjs → acorex-modules-assessment-management-questionnaire-viewer-popup.component-D9I3S-ZT.mjs} +125 -124
- package/fesm2022/acorex-modules-assessment-management-questionnaire-viewer-popup.component-D9I3S-ZT.mjs.map +1 -0
- package/fesm2022/{acorex-modules-assessment-management-questionnaire.entity-RWSkzNbA.mjs → acorex-modules-assessment-management-questionnaire.entity-D9nHUmQB.mjs} +12 -36
- package/fesm2022/acorex-modules-assessment-management-questionnaire.entity-D9nHUmQB.mjs.map +1 -0
- package/fesm2022/acorex-modules-assessment-management-view-session-answers.command-BOeO3Dit.mjs +350 -0
- package/fesm2022/acorex-modules-assessment-management-view-session-answers.command-BOeO3Dit.mjs.map +1 -0
- package/fesm2022/acorex-modules-assessment-management.mjs +1 -1
- package/fesm2022/acorex-modules-common.mjs +1 -8
- package/fesm2022/acorex-modules-common.mjs.map +1 -1
- package/fesm2022/{acorex-modules-human-capital-management-acorex-modules-human-capital-management-BWezAea1.mjs → acorex-modules-human-capital-management-acorex-modules-human-capital-management-uRz1c5Km.mjs} +20 -20
- package/fesm2022/{acorex-modules-human-capital-management-acorex-modules-human-capital-management-BWezAea1.mjs.map → acorex-modules-human-capital-management-acorex-modules-human-capital-management-uRz1c5Km.mjs.map} +1 -1
- package/fesm2022/{acorex-modules-human-capital-management-approve-leave-request.command-Bh_Bbq5-.mjs → acorex-modules-human-capital-management-approve-leave-request.command-23klKnTy.mjs} +2 -2
- package/fesm2022/{acorex-modules-human-capital-management-approve-leave-request.command-Bh_Bbq5-.mjs.map → acorex-modules-human-capital-management-approve-leave-request.command-23klKnTy.mjs.map} +1 -1
- package/fesm2022/{acorex-modules-human-capital-management-assign-position-assignment.command-BpDdDG9i.mjs → acorex-modules-human-capital-management-assign-position-assignment.command-BJ8xUiR2.mjs} +2 -2
- package/fesm2022/{acorex-modules-human-capital-management-assign-position-assignment.command-BpDdDG9i.mjs.map → acorex-modules-human-capital-management-assign-position-assignment.command-BJ8xUiR2.mjs.map} +1 -1
- package/fesm2022/{acorex-modules-human-capital-management-cancel-leave-request.command-CjtKaKFw.mjs → acorex-modules-human-capital-management-cancel-leave-request.command-B3u1gXWI.mjs} +2 -2
- package/fesm2022/{acorex-modules-human-capital-management-cancel-leave-request.command-CjtKaKFw.mjs.map → acorex-modules-human-capital-management-cancel-leave-request.command-B3u1gXWI.mjs.map} +1 -1
- package/fesm2022/{acorex-modules-human-capital-management-employee.entity-Cx_oY2aK.mjs → acorex-modules-human-capital-management-employee.entity-uhwOOw_y.mjs} +11 -3
- package/fesm2022/acorex-modules-human-capital-management-employee.entity-uhwOOw_y.mjs.map +1 -0
- package/fesm2022/{acorex-modules-human-capital-management-employment-type.entity-B20Taa5x.mjs → acorex-modules-human-capital-management-employment-type.entity-BQe82rsr.mjs} +2 -2
- package/fesm2022/{acorex-modules-human-capital-management-employment-type.entity-B20Taa5x.mjs.map → acorex-modules-human-capital-management-employment-type.entity-BQe82rsr.mjs.map} +1 -1
- package/fesm2022/{acorex-modules-human-capital-management-leave-request.entity-BO8QXpZE.mjs → acorex-modules-human-capital-management-leave-request.entity-CE4hs4C8.mjs} +2 -2
- package/fesm2022/{acorex-modules-human-capital-management-leave-request.entity-BO8QXpZE.mjs.map → acorex-modules-human-capital-management-leave-request.entity-CE4hs4C8.mjs.map} +1 -1
- package/fesm2022/{acorex-modules-human-capital-management-leave-type.entity-CQwSWqSh.mjs → acorex-modules-human-capital-management-leave-type.entity-DJ4EEUKg.mjs} +2 -2
- package/fesm2022/{acorex-modules-human-capital-management-leave-type.entity-CQwSWqSh.mjs.map → acorex-modules-human-capital-management-leave-type.entity-DJ4EEUKg.mjs.map} +1 -1
- package/fesm2022/{acorex-modules-human-capital-management-lifecycle-event-type.entity-BPWJrvbN.mjs → acorex-modules-human-capital-management-lifecycle-event-type.entity-CB2hlyOP.mjs} +2 -2
- package/fesm2022/{acorex-modules-human-capital-management-lifecycle-event-type.entity-BPWJrvbN.mjs.map → acorex-modules-human-capital-management-lifecycle-event-type.entity-CB2hlyOP.mjs.map} +1 -1
- package/fesm2022/{acorex-modules-human-capital-management-lifecycle-event.entity-ZZuPu9KQ.mjs → acorex-modules-human-capital-management-lifecycle-event.entity-DWonFZpU.mjs} +2 -2
- package/fesm2022/{acorex-modules-human-capital-management-lifecycle-event.entity-ZZuPu9KQ.mjs.map → acorex-modules-human-capital-management-lifecycle-event.entity-DWonFZpU.mjs.map} +1 -1
- package/fesm2022/{acorex-modules-human-capital-management-position-assignment.entity-BN1y0qhi.mjs → acorex-modules-human-capital-management-position-assignment.entity-o8PjggiT.mjs} +2 -2
- package/fesm2022/{acorex-modules-human-capital-management-position-assignment.entity-BN1y0qhi.mjs.map → acorex-modules-human-capital-management-position-assignment.entity-o8PjggiT.mjs.map} +1 -1
- package/fesm2022/{acorex-modules-human-capital-management-reject-leave-request.command-LczqOHP-.mjs → acorex-modules-human-capital-management-reject-leave-request.command-B6sr7oey.mjs} +2 -2
- package/fesm2022/{acorex-modules-human-capital-management-reject-leave-request.command-LczqOHP-.mjs.map → acorex-modules-human-capital-management-reject-leave-request.command-B6sr7oey.mjs.map} +1 -1
- package/fesm2022/{acorex-modules-human-capital-management-revoke-position-assignment.command-Dm8YacDI.mjs → acorex-modules-human-capital-management-revoke-position-assignment.command-aH7qTRnr.mjs} +2 -2
- package/fesm2022/{acorex-modules-human-capital-management-revoke-position-assignment.command-Dm8YacDI.mjs.map → acorex-modules-human-capital-management-revoke-position-assignment.command-aH7qTRnr.mjs.map} +1 -1
- package/fesm2022/{acorex-modules-human-capital-management-start-lifecycle-event-flow.command-DPwuyFz2.mjs → acorex-modules-human-capital-management-start-lifecycle-event-flow.command-B-VsXS4c.mjs} +2 -2
- package/fesm2022/{acorex-modules-human-capital-management-start-lifecycle-event-flow.command-DPwuyFz2.mjs.map → acorex-modules-human-capital-management-start-lifecycle-event-flow.command-B-VsXS4c.mjs.map} +1 -1
- package/fesm2022/acorex-modules-human-capital-management.mjs +1 -1
- package/fesm2022/acorex-modules-report-management.mjs +1 -1
- package/fesm2022/acorex-modules-report-management.mjs.map +1 -1
- package/fesm2022/{acorex-modules-task-management-acorex-modules-task-management--mdNdYIs.mjs → acorex-modules-task-management-acorex-modules-task-management-DAh3IByo.mjs} +37 -19
- package/fesm2022/acorex-modules-task-management-acorex-modules-task-management-DAh3IByo.mjs.map +1 -0
- package/fesm2022/{acorex-modules-task-management-task-board.page-BIZ1qH7m.mjs → acorex-modules-task-management-task-board.page-C2hB9JPM.mjs} +21 -12
- package/fesm2022/acorex-modules-task-management-task-board.page-C2hB9JPM.mjs.map +1 -0
- package/fesm2022/acorex-modules-task-management.mjs +1 -1
- package/package.json +2 -2
- package/types/acorex-modules-assessment-management.d.ts +391 -271
- package/types/acorex-modules-common.d.ts +1 -0
- package/types/acorex-modules-task-management.d.ts +14 -1
- package/fesm2022/acorex-modules-assessment-management-acorex-modules-assessment-management-o8aFazwA.mjs.map +0 -1
- package/fesm2022/acorex-modules-assessment-management-assessment-case.entity-yrc_Yybq.mjs.map +0 -1
- package/fesm2022/acorex-modules-assessment-management-assessment-session-answers-view.util-BUQa_TSY.mjs +0 -47
- package/fesm2022/acorex-modules-assessment-management-assessment-session-answers-view.util-BUQa_TSY.mjs.map +0 -1
- package/fesm2022/acorex-modules-assessment-management-assessment-session.entity-Cwf30iuu.mjs.map +0 -1
- package/fesm2022/acorex-modules-assessment-management-fill-assessment-session.command-CJieLR5g.mjs.map +0 -1
- package/fesm2022/acorex-modules-assessment-management-index-D8KjfHAH.mjs +0 -1509
- package/fesm2022/acorex-modules-assessment-management-index-D8KjfHAH.mjs.map +0 -1
- package/fesm2022/acorex-modules-assessment-management-preview-question.command-D0-FB1HH.mjs.map +0 -1
- package/fesm2022/acorex-modules-assessment-management-question-bank-interface-editor-widget-edit.component-DYyUhSWd.mjs.map +0 -1
- package/fesm2022/acorex-modules-assessment-management-questionnaire-calculation.entity-CYF0k42_.mjs +0 -236
- package/fesm2022/acorex-modules-assessment-management-questionnaire-calculation.entity-CYF0k42_.mjs.map +0 -1
- package/fesm2022/acorex-modules-assessment-management-questionnaire-viewer-popup.component-Cy5ElBmU.mjs.map +0 -1
- package/fesm2022/acorex-modules-assessment-management-questionnaire.entity-RWSkzNbA.mjs.map +0 -1
- package/fesm2022/acorex-modules-assessment-management-save-questionnaire-questions.command-koGmUbNE.mjs +0 -61
- package/fesm2022/acorex-modules-assessment-management-save-questionnaire-questions.command-koGmUbNE.mjs.map +0 -1
- package/fesm2022/acorex-modules-assessment-management-view-case-last-session-answers.command-NTuDdoYk.mjs +0 -157
- package/fesm2022/acorex-modules-assessment-management-view-case-last-session-answers.command-NTuDdoYk.mjs.map +0 -1
- package/fesm2022/acorex-modules-assessment-management-view-session-answers.command-0btGV66_.mjs +0 -172
- package/fesm2022/acorex-modules-assessment-management-view-session-answers.command-0btGV66_.mjs.map +0 -1
- package/fesm2022/acorex-modules-human-capital-management-employee.entity-Cx_oY2aK.mjs.map +0 -1
- package/fesm2022/acorex-modules-task-management-acorex-modules-task-management--mdNdYIs.mjs.map +0 -1
- package/fesm2022/acorex-modules-task-management-task-board.page-BIZ1qH7m.mjs.map +0 -1
|
@@ -1,48 +1,53 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { inject, Injector, Injectable, NgModule,
|
|
2
|
+
import { inject, Injector, Injectable, NgModule, input, output, signal, viewChild, computed, effect, untracked, ChangeDetectionStrategy, Component, ViewEncapsulation, ElementRef, afterNextRender } from '@angular/core';
|
|
3
3
|
import { AXPCommonMenuKeys } from '@acorex/modules/common';
|
|
4
|
-
import { AXPEntityService, AXP_ENTITY_DEFINITION_LOADER } from '@acorex/platform/layout/entity';
|
|
5
|
-
import { AXPSearchCommandProvider, createEntityCommandOptions, AXPFileStorageService, AXPStickyDirective, AXP_STATUS_PROVIDERS, AXP_MENU_PROVIDER, AXP_SEARCH_PROVIDER } from '@acorex/platform/common';
|
|
4
|
+
import { AXPEntityService, AXPEntityDefinitionRegistryService, AXPEntityEventsKeys, AXP_ENTITY_DEFINITION_LOADER } from '@acorex/platform/layout/entity';
|
|
5
|
+
import { AXPSearchCommandProvider, createEntityCommandOptions, AXPFileStorageService, AXPStickyDirective, AXP_STATUS_PROVIDERS, AXP_MENU_PROVIDER, AXP_SEARCH_PROVIDER, AXPSystemStatusType } from '@acorex/platform/common';
|
|
6
6
|
import { AXPAuthGuard, AXP_PERMISSION_DEFINITION_PROVIDER, AXPSessionService } from '@acorex/platform/auth';
|
|
7
|
-
import { AXPStateMessageComponent, AXP_PAGE_COMPONENT_PROVIDER, AXPThemeLayoutBlockComponent, AXPStopwatchComponent } from '@acorex/platform/layout/components';
|
|
8
|
-
import { provideCommandSetups, provideCommand } from '@acorex/platform/runtime';
|
|
9
|
-
import { AXPExpressionEvaluatorService, AXPDeviceService, containsHtmlMarkup, AXP_EXPRESSION_EVALUATOR_SCOPE_PROVIDER, AXP_MODULE_MANIFEST_PROVIDER, provideLazyProvider, AXP_FEATURE_DEFINITION_PROVIDER, AXPContextStore } from '@acorex/platform/core';
|
|
7
|
+
import { AXPDataSelectorService, AXPPropertyViewerService, AXPStandardSectionItemsBuilderComponent, AXPStateMessageComponent, AXP_PAGE_COMPONENT_PROVIDER, AXPOutcomeResultsViewerComponent, AXPThemeLayoutBlockComponent, AXPStopwatchComponent } from '@acorex/platform/layout/components';
|
|
8
|
+
import { AXPCommandService, provideCommandSetups, provideCommand } from '@acorex/platform/runtime';
|
|
9
|
+
import { AXPExpressionEvaluatorService, AXPDeviceService, AXPBroadcastEventService, AXPDataGenerator, containsHtmlMarkup, AXP_EXPRESSION_EVALUATOR_SCOPE_PROVIDER, AXP_MODULE_MANIFEST_PROVIDER, provideLazyProvider, AXP_FEATURE_DEFINITION_PROVIDER, AXPContextStore } from '@acorex/platform/core';
|
|
10
10
|
import { ROUTES, ActivatedRoute, Router } from '@angular/router';
|
|
11
11
|
import { AXPRootLayoutComponent } from '@acorex/platform/themes/default';
|
|
12
12
|
import { AXMMetaDataDefinitionEntityModule } from '@acorex/modules/data-management';
|
|
13
|
-
import * as i1 from '@acorex/platform/layout/widget-core';
|
|
14
|
-
import { AXPWidgetGroupEnum, AXP_WIDGETS_EDITOR_CATEGORY, AXPWidgetCoreModule, AXP_WIDGET_DEFINITION_PROVIDER, AXPWidgetContainerComponent, AXPWidgetCoreService } from '@acorex/platform/layout/widget-core';
|
|
13
|
+
import * as i1$1 from '@acorex/platform/layout/widget-core';
|
|
14
|
+
import { AXPWidgetGroupEnum, AXP_WIDGETS_EDITOR_CATEGORY, AXPWidgetCoreModule, AXP_WIDGET_DEFINITION_PROVIDER, AXPWidgetsCatalog, createBooleanProperty, AXPWidgetRegistryService, AXPWidgetContainerComponent, AXPWidgetCoreService } from '@acorex/platform/layout/widget-core';
|
|
15
15
|
import { AXP_NAME_PROPERTY, AXP_DATA_PATH_PROPERTY } from '@acorex/platform/layout/widgets';
|
|
16
16
|
import * as i3 from '@angular/common';
|
|
17
17
|
import { CommonModule, AsyncPipe } from '@angular/common';
|
|
18
18
|
import * as i1$3 from '@acorex/components/form';
|
|
19
19
|
import { AXFormModule } from '@acorex/components/form';
|
|
20
|
-
import * as i4
|
|
21
|
-
import { resolveMultiLanguageString, AXTranslationService, AXTranslationModule } from '@acorex/core/translation';
|
|
22
|
-
import * as i2
|
|
20
|
+
import * as i4 from '@acorex/core/translation';
|
|
21
|
+
import { resolveMultiLanguageString, AXTranslationService, AXTranslationModule, createMultiLanguageString, isEffectivelyEmptyLocalizedValue } from '@acorex/core/translation';
|
|
22
|
+
import * as i2 from '@acorex/components/decorators';
|
|
23
23
|
import { AXDecoratorModule } from '@acorex/components/decorators';
|
|
24
24
|
import { AXToastService } from '@acorex/components/toast';
|
|
25
25
|
import { signalStore, withState, withComputed, withMethods, patchState } from '@ngrx/signals';
|
|
26
|
-
import { cloneDeep, get } from 'lodash-es';
|
|
26
|
+
import { cloneDeep, get, isEqual, isNil, first, defaultTo, isEmpty, isObject } from 'lodash-es';
|
|
27
|
+
import { AXDataSource } from '@acorex/cdk/common';
|
|
28
|
+
import { AXFullScreenDirective } from '@acorex/cdk/full-screen';
|
|
29
|
+
import * as i1 from '@acorex/components/button';
|
|
30
|
+
import { AXButtonModule } from '@acorex/components/button';
|
|
31
|
+
import { AXDropdownModule } from '@acorex/components/dropdown';
|
|
32
|
+
import { AXLabelModule } from '@acorex/components/label';
|
|
33
|
+
import { AXSwitchModule } from '@acorex/components/switch';
|
|
34
|
+
import * as i5 from '@angular/forms';
|
|
35
|
+
import { FormsModule } from '@angular/forms';
|
|
27
36
|
import { AXPopupService } from '@acorex/components/popup';
|
|
28
|
-
import
|
|
37
|
+
import { AXPPageLayoutBaseComponent, AXPPageLayoutBase, AXPPageLayoutComponent } from '@acorex/platform/layout/views';
|
|
38
|
+
import * as i2$1 from '@acorex/components/alert';
|
|
29
39
|
import { AXAlertModule } from '@acorex/components/alert';
|
|
30
|
-
import * as i4 from '@acorex/components/text-area';
|
|
40
|
+
import * as i4$1 from '@acorex/components/text-area';
|
|
31
41
|
import { AXTextAreaModule } from '@acorex/components/text-area';
|
|
32
42
|
import { AXSafePipe } from '@acorex/core/pipes';
|
|
33
|
-
import * as i5 from '@angular/forms';
|
|
34
|
-
import { FormsModule } from '@angular/forms';
|
|
35
43
|
import { AXDrawerDirectiveModule } from '@acorex/cdk/drawer';
|
|
36
44
|
import { AXResizableDirective } from '@acorex/cdk/resizable';
|
|
37
45
|
import * as i2$2 from '@acorex/components/badge';
|
|
38
46
|
import { AXBadgeModule } from '@acorex/components/badge';
|
|
39
|
-
import * as i1$2 from '@acorex/components/button';
|
|
40
|
-
import { AXButtonModule } from '@acorex/components/button';
|
|
41
47
|
import * as i3$1 from '@acorex/components/drawer';
|
|
42
48
|
import { AXDrawerModule } from '@acorex/components/drawer';
|
|
43
|
-
import * as i1$
|
|
49
|
+
import * as i1$2 from '@acorex/components/tabs';
|
|
44
50
|
import { AXTabsComponent, AXTabsModule } from '@acorex/components/tabs';
|
|
45
|
-
import { AXPPageLayoutBaseComponent, AXPPageLayoutComponent, AXPPageLayoutBase } from '@acorex/platform/layout/views';
|
|
46
51
|
import { DomSanitizer } from '@angular/platform-browser';
|
|
47
52
|
|
|
48
53
|
//#region ---- Root Configuration ----
|
|
@@ -81,12 +86,6 @@ const RootConfig = {
|
|
|
81
86
|
titlePlural: '@assessment-management:sessions.entities.assessment-session.plural',
|
|
82
87
|
icon: 'fa-light fa-clipboard-check',
|
|
83
88
|
},
|
|
84
|
-
questionnaireCalculation: {
|
|
85
|
-
name: 'QuestionnaireCalculation',
|
|
86
|
-
title: '@assessment-management:questionnaire-calculations.entities.questionnaire-calculation.title',
|
|
87
|
-
titlePlural: '@assessment-management:questionnaire-calculations.entities.questionnaire-calculation.plural',
|
|
88
|
-
icon: 'fa-light fa-calculator',
|
|
89
|
-
},
|
|
90
89
|
},
|
|
91
90
|
};
|
|
92
91
|
//#endregion
|
|
@@ -102,15 +101,13 @@ class AXMAssessmentManagementEntityProvider {
|
|
|
102
101
|
if (moduleName === RootConfig.module.name) {
|
|
103
102
|
switch (entityName) {
|
|
104
103
|
case RootConfig.entities.questionBankItem.name:
|
|
105
|
-
return (await import('./acorex-modules-assessment-management-question-bank-item.entity-
|
|
104
|
+
return (await import('./acorex-modules-assessment-management-question-bank-item.entity-Cw2WCdYK.mjs')).factory(this.injector);
|
|
106
105
|
case RootConfig.entities.questionnaire.name:
|
|
107
|
-
return (await import('./acorex-modules-assessment-management-questionnaire.entity-
|
|
106
|
+
return (await import('./acorex-modules-assessment-management-questionnaire.entity-D9nHUmQB.mjs')).factory();
|
|
108
107
|
case RootConfig.entities.assessmentCase.name:
|
|
109
|
-
return (await import('./acorex-modules-assessment-management-assessment-case.entity-
|
|
108
|
+
return (await import('./acorex-modules-assessment-management-assessment-case.entity-DhVwPz0T.mjs')).factory(this.injector);
|
|
110
109
|
case RootConfig.entities.assessmentSession.name:
|
|
111
|
-
return (await import('./acorex-modules-assessment-management-assessment-session.entity-
|
|
112
|
-
case RootConfig.entities.questionnaireCalculation.name:
|
|
113
|
-
return (await import('./acorex-modules-assessment-management-questionnaire-calculation.entity-CYF0k42_.mjs')).factory(this.injector);
|
|
110
|
+
return (await import('./acorex-modules-assessment-management-assessment-session.entity-BvV2Qgw1.mjs')).factory(this.injector);
|
|
114
111
|
}
|
|
115
112
|
}
|
|
116
113
|
return null;
|
|
@@ -177,9 +174,6 @@ const AXMAssessmentManagementPermissionKeys = {
|
|
|
177
174
|
Session: {
|
|
178
175
|
Management: 'AssessmentManagement:Session:Management',
|
|
179
176
|
},
|
|
180
|
-
QuestionnaireCalculation: {
|
|
181
|
-
Management: 'AssessmentManagement:QuestionnaireCalculation:Management',
|
|
182
|
-
},
|
|
183
177
|
Automation: {
|
|
184
178
|
Management: 'AssessmentManagement:Automation:Management',
|
|
185
179
|
},
|
|
@@ -270,7 +264,6 @@ class AXMAssessmentManagementPermissionDefinitionProvider {
|
|
|
270
264
|
const QUESTIONNAIRE_PERMISSIONS = '@assessment-management:questionnaires.permissions.questionnaire';
|
|
271
265
|
const CASE_PERMISSIONS = '@assessment-management:cases.permissions.assessment-case';
|
|
272
266
|
const SESSION_PERMISSIONS = '@assessment-management:sessions.permissions.assessment-session';
|
|
273
|
-
const QUESTIONNAIRE_CALCULATION_PERMISSIONS = '@assessment-management:questionnaire-calculations.permissions.questionnaire-calculation';
|
|
274
267
|
const AUTOMATION_PERMISSIONS = '@assessment-management:automations.permissions.automation';
|
|
275
268
|
context
|
|
276
269
|
.addGroup(RootConfig.module.name, `${MODULE_PERMISSIONS}.title`, `${MODULE_PERMISSIONS}.description`)
|
|
@@ -289,9 +282,6 @@ class AXMAssessmentManagementPermissionDefinitionProvider {
|
|
|
289
282
|
// AssessmentSession Permissions (view-only; sessions are created by workflows)
|
|
290
283
|
.addPermission(keys.Session.Management, `${SESSION_PERMISSIONS}.management.title`, `${SESSION_PERMISSIONS}.management.description`)
|
|
291
284
|
.endPermission()
|
|
292
|
-
// QuestionnaireCalculation Permissions
|
|
293
|
-
.addPermission(keys.QuestionnaireCalculation.Management, `${QUESTIONNAIRE_CALCULATION_PERMISSIONS}.management.title`, `${QUESTIONNAIRE_CALCULATION_PERMISSIONS}.management.description`)
|
|
294
|
-
.endPermission()
|
|
295
285
|
// Automation Permissions
|
|
296
286
|
.addPermission(keys.Automation.Management, `${AUTOMATION_PERMISSIONS}.management.title`, `${AUTOMATION_PERMISSIONS}.management.description`)
|
|
297
287
|
.endPermission()
|
|
@@ -440,10 +430,10 @@ const AXMQuestionBankInterfaceEditorWidget = {
|
|
|
440
430
|
],
|
|
441
431
|
components: {
|
|
442
432
|
edit: {
|
|
443
|
-
component: () => import('./acorex-modules-assessment-management-question-bank-interface-editor-widget-edit.component-
|
|
433
|
+
component: () => import('./acorex-modules-assessment-management-question-bank-interface-editor-widget-edit.component-B2ES-zcL.mjs').then((c) => c.AXMQuestionBankInterfaceEditorWidgetEditComponent),
|
|
444
434
|
},
|
|
445
435
|
designer: {
|
|
446
|
-
component: () => import('./acorex-modules-assessment-management-question-bank-interface-editor-widget-edit.component-
|
|
436
|
+
component: () => import('./acorex-modules-assessment-management-question-bank-interface-editor-widget-edit.component-B2ES-zcL.mjs').then((c) => c.AXMQuestionBankInterfaceEditorWidgetEditComponent),
|
|
447
437
|
},
|
|
448
438
|
column: {
|
|
449
439
|
component: () => import('@acorex/platform/layout/widgets').then((m) => m.AXPWidgetFieldConfiguratorWidgetColumnComponent),
|
|
@@ -998,6 +988,279 @@ function allocateNextQuestionItemName(used) {
|
|
|
998
988
|
}
|
|
999
989
|
//#endregion
|
|
1000
990
|
|
|
991
|
+
//#region ---- Imports ----
|
|
992
|
+
const DEFAULT_PRE_QUESTIONNAIRE_CONFIG = { enabled: false };
|
|
993
|
+
const DEFAULT_POST_QUESTIONNAIRE_CONFIG = {
|
|
994
|
+
reviewEnabled: false,
|
|
995
|
+
summaryEnabled: false,
|
|
996
|
+
showOutcomeResults: false,
|
|
997
|
+
};
|
|
998
|
+
const DEFAULT_QUESTIONNAIRE_ENTITY_DISPLAY = {
|
|
999
|
+
viewMode: 'single-page',
|
|
1000
|
+
showProgressBar: true,
|
|
1001
|
+
showTimer: false,
|
|
1002
|
+
showQuestionNumbers: true,
|
|
1003
|
+
validationStrategy: 'step',
|
|
1004
|
+
completionMode: 'submit-only',
|
|
1005
|
+
};
|
|
1006
|
+
const OUTCOME_DISPLAY_OPERATORS = [
|
|
1007
|
+
'eq',
|
|
1008
|
+
'neq',
|
|
1009
|
+
'gt',
|
|
1010
|
+
'gte',
|
|
1011
|
+
'lt',
|
|
1012
|
+
'lte',
|
|
1013
|
+
];
|
|
1014
|
+
const OUTCOME_DISPLAY_EMPHASIS = ['normal', 'medium', 'bold'];
|
|
1015
|
+
function normalizeOutcomeDisplayColor(value) {
|
|
1016
|
+
if (typeof value !== 'string') {
|
|
1017
|
+
return undefined;
|
|
1018
|
+
}
|
|
1019
|
+
const trimmed = value.trim();
|
|
1020
|
+
const parts = trimmed.split(/\s+/);
|
|
1021
|
+
if (parts.length !== 3) {
|
|
1022
|
+
return undefined;
|
|
1023
|
+
}
|
|
1024
|
+
return trimmed;
|
|
1025
|
+
}
|
|
1026
|
+
function normalizeOutcomeDisplayOperator(value) {
|
|
1027
|
+
const raw = typeof value === 'string'
|
|
1028
|
+
? value
|
|
1029
|
+
: typeof value === 'object' && value !== null && 'id' in value
|
|
1030
|
+
? String(value.id ?? '')
|
|
1031
|
+
: '';
|
|
1032
|
+
const normalized = raw.trim().toLowerCase();
|
|
1033
|
+
return OUTCOME_DISPLAY_OPERATORS.includes(normalized)
|
|
1034
|
+
? normalized
|
|
1035
|
+
: undefined;
|
|
1036
|
+
}
|
|
1037
|
+
function normalizeOutcomeDisplayCompareValue(value) {
|
|
1038
|
+
if (typeof value === 'number' && Number.isFinite(value)) {
|
|
1039
|
+
return value;
|
|
1040
|
+
}
|
|
1041
|
+
if (typeof value === 'boolean') {
|
|
1042
|
+
return value;
|
|
1043
|
+
}
|
|
1044
|
+
if (typeof value === 'string') {
|
|
1045
|
+
const trimmed = value.trim();
|
|
1046
|
+
if (!trimmed) {
|
|
1047
|
+
return undefined;
|
|
1048
|
+
}
|
|
1049
|
+
if (trimmed === 'true')
|
|
1050
|
+
return true;
|
|
1051
|
+
if (trimmed === 'false')
|
|
1052
|
+
return false;
|
|
1053
|
+
const asNumber = Number(trimmed);
|
|
1054
|
+
if (Number.isFinite(asNumber)) {
|
|
1055
|
+
return asNumber;
|
|
1056
|
+
}
|
|
1057
|
+
return trimmed;
|
|
1058
|
+
}
|
|
1059
|
+
return undefined;
|
|
1060
|
+
}
|
|
1061
|
+
function normalizeOutcomeDisplayEmphasis(value) {
|
|
1062
|
+
const raw = typeof value === 'string'
|
|
1063
|
+
? value
|
|
1064
|
+
: typeof value === 'object' && value !== null && 'id' in value
|
|
1065
|
+
? String(value.id ?? '')
|
|
1066
|
+
: '';
|
|
1067
|
+
const normalized = raw.trim().toLowerCase();
|
|
1068
|
+
return OUTCOME_DISPLAY_EMPHASIS.includes(normalized)
|
|
1069
|
+
? normalized
|
|
1070
|
+
: 'normal';
|
|
1071
|
+
}
|
|
1072
|
+
function normalizeOutcomeDisplayIcon(icon) {
|
|
1073
|
+
if (icon == null || icon === '') {
|
|
1074
|
+
return undefined;
|
|
1075
|
+
}
|
|
1076
|
+
if (typeof icon === 'string') {
|
|
1077
|
+
const trimmed = icon.trim();
|
|
1078
|
+
return trimmed.length > 0 ? trimmed : undefined;
|
|
1079
|
+
}
|
|
1080
|
+
const styleClass = String(icon.styleClass ?? '').trim();
|
|
1081
|
+
const iconClass = String(icon.iconClass ?? '').trim();
|
|
1082
|
+
const combined = [styleClass, iconClass].filter(Boolean).join(' ');
|
|
1083
|
+
return combined.length > 0 ? combined : undefined;
|
|
1084
|
+
}
|
|
1085
|
+
/** Parses a theme color chooser value into foreground, background, and border parts. */
|
|
1086
|
+
function parseQuestionnaireOutcomeDisplayColor(value) {
|
|
1087
|
+
if (!value?.trim()) {
|
|
1088
|
+
return null;
|
|
1089
|
+
}
|
|
1090
|
+
const parts = value.trim().split(/\s+/);
|
|
1091
|
+
if (parts.length !== 3) {
|
|
1092
|
+
return null;
|
|
1093
|
+
}
|
|
1094
|
+
return {
|
|
1095
|
+
foreground: parts[0],
|
|
1096
|
+
background: parts[1],
|
|
1097
|
+
border: parts[2],
|
|
1098
|
+
};
|
|
1099
|
+
}
|
|
1100
|
+
function isQuestionnaireOutcomeDisplayColorHex(value) {
|
|
1101
|
+
return value.trim().startsWith('#');
|
|
1102
|
+
}
|
|
1103
|
+
/**
|
|
1104
|
+
* Returns true when the evaluated outcome value matches the display rule condition.
|
|
1105
|
+
*/
|
|
1106
|
+
function matchesQuestionnaireOutcomeDisplayRule(value, rule) {
|
|
1107
|
+
const right = rule.compareValue;
|
|
1108
|
+
switch (rule.operator) {
|
|
1109
|
+
case 'eq':
|
|
1110
|
+
return value == right;
|
|
1111
|
+
case 'neq':
|
|
1112
|
+
return value != right;
|
|
1113
|
+
case 'gt':
|
|
1114
|
+
return Number(value) > Number(right);
|
|
1115
|
+
case 'gte':
|
|
1116
|
+
return Number(value) >= Number(right);
|
|
1117
|
+
case 'lt':
|
|
1118
|
+
return Number(value) < Number(right);
|
|
1119
|
+
case 'lte':
|
|
1120
|
+
return Number(value) <= Number(right);
|
|
1121
|
+
default:
|
|
1122
|
+
return false;
|
|
1123
|
+
}
|
|
1124
|
+
}
|
|
1125
|
+
function normalizeQuestionnaireOutcomeDisplayRules(rules) {
|
|
1126
|
+
if (!Array.isArray(rules)) {
|
|
1127
|
+
return [];
|
|
1128
|
+
}
|
|
1129
|
+
const normalized = [];
|
|
1130
|
+
for (const [index, rule] of rules.entries()) {
|
|
1131
|
+
const operator = normalizeOutcomeDisplayOperator(rule?.operator);
|
|
1132
|
+
const compareValue = normalizeOutcomeDisplayCompareValue(rule?.compareValue);
|
|
1133
|
+
const color = normalizeOutcomeDisplayColor(rule?.color);
|
|
1134
|
+
if (!operator || compareValue === undefined || !color) {
|
|
1135
|
+
continue;
|
|
1136
|
+
}
|
|
1137
|
+
normalized.push({
|
|
1138
|
+
id: String(rule?.id ?? '').trim() || `rule-${index + 1}`,
|
|
1139
|
+
order: rule?.order ?? index,
|
|
1140
|
+
operator,
|
|
1141
|
+
compareValue,
|
|
1142
|
+
color,
|
|
1143
|
+
emphasis: normalizeOutcomeDisplayEmphasis(rule?.emphasis),
|
|
1144
|
+
icon: normalizeOutcomeDisplayIcon(rule?.icon),
|
|
1145
|
+
});
|
|
1146
|
+
}
|
|
1147
|
+
return normalized.sort((a, b) => a.order - b.order);
|
|
1148
|
+
}
|
|
1149
|
+
const DEFAULT_QUESTIONNAIRE_OUTCOMES = { sections: [] };
|
|
1150
|
+
function normalizeQuestionnaireOutcomesValue(value) {
|
|
1151
|
+
const sections = value?.sections;
|
|
1152
|
+
if (!Array.isArray(sections)) {
|
|
1153
|
+
return { sections: [] };
|
|
1154
|
+
}
|
|
1155
|
+
return {
|
|
1156
|
+
sections: sections.map((section, index) => ({
|
|
1157
|
+
...section,
|
|
1158
|
+
name: (section.name ?? '').trim() || `section-${index + 1}`,
|
|
1159
|
+
order: section.order ?? index,
|
|
1160
|
+
items: Array.isArray(section.items)
|
|
1161
|
+
? section.items.map((item) => ({
|
|
1162
|
+
...item,
|
|
1163
|
+
displayRules: normalizeQuestionnaireOutcomeDisplayRules(item.displayRules),
|
|
1164
|
+
}))
|
|
1165
|
+
: [],
|
|
1166
|
+
})),
|
|
1167
|
+
};
|
|
1168
|
+
}
|
|
1169
|
+
/** All outcome items across sections (evaluation, automations, duplicate checks). */
|
|
1170
|
+
function flattenQuestionnaireOutcomeItems(value) {
|
|
1171
|
+
return normalizeQuestionnaireOutcomesValue(value).sections.flatMap((section) => section.items);
|
|
1172
|
+
}
|
|
1173
|
+
function findDuplicateOutcomeNames(value) {
|
|
1174
|
+
const seen = new Map();
|
|
1175
|
+
for (const item of flattenQuestionnaireOutcomeItems(value)) {
|
|
1176
|
+
const key = (item.name ?? '').trim();
|
|
1177
|
+
if (!key)
|
|
1178
|
+
continue;
|
|
1179
|
+
seen.set(key, (seen.get(key) ?? 0) + 1);
|
|
1180
|
+
}
|
|
1181
|
+
return Array.from(seen.entries())
|
|
1182
|
+
.filter(([, count]) => count > 1)
|
|
1183
|
+
.map(([name]) => name);
|
|
1184
|
+
}
|
|
1185
|
+
/**
|
|
1186
|
+
* Maps entity pre/post to viewer config (defaults when omitted).
|
|
1187
|
+
*/
|
|
1188
|
+
function toPrePostConfig(q) {
|
|
1189
|
+
if (!q) {
|
|
1190
|
+
return null;
|
|
1191
|
+
}
|
|
1192
|
+
const pre = {
|
|
1193
|
+
...DEFAULT_PRE_QUESTIONNAIRE_CONFIG,
|
|
1194
|
+
...q.pre,
|
|
1195
|
+
enabled: q.pre?.enabled === true,
|
|
1196
|
+
};
|
|
1197
|
+
const post = {
|
|
1198
|
+
...DEFAULT_POST_QUESTIONNAIRE_CONFIG,
|
|
1199
|
+
...q.post,
|
|
1200
|
+
reviewEnabled: q.post?.reviewEnabled === true,
|
|
1201
|
+
summaryEnabled: q.post?.summaryEnabled === true,
|
|
1202
|
+
showOutcomeResults: q.post?.showOutcomeResults === true,
|
|
1203
|
+
};
|
|
1204
|
+
return { pre, post };
|
|
1205
|
+
}
|
|
1206
|
+
const VIEW_MODE_VALUES = ['single-page', 'page-per-group', 'page-per-question', 'side-menu'];
|
|
1207
|
+
const VALIDATION_STRATEGY_VALUES = ['step', 'end'];
|
|
1208
|
+
const COMPLETION_MODE_VALUES = ['submit-only', 'save-and-continue'];
|
|
1209
|
+
/**
|
|
1210
|
+
* Coerces stored view mode (string or SelectBox `{ id }`) to a known value.
|
|
1211
|
+
*/
|
|
1212
|
+
function normalizeViewMode(value) {
|
|
1213
|
+
if (typeof value === 'string' && VIEW_MODE_VALUES.includes(value)) {
|
|
1214
|
+
return value;
|
|
1215
|
+
}
|
|
1216
|
+
if (value != null && typeof value === 'object' && 'id' in value && typeof value.id === 'string') {
|
|
1217
|
+
return normalizeViewMode(value.id);
|
|
1218
|
+
}
|
|
1219
|
+
return 'single-page';
|
|
1220
|
+
}
|
|
1221
|
+
/**
|
|
1222
|
+
* Coerces stored validation strategy (string or SelectBox `{ id }`) to a known value.
|
|
1223
|
+
*/
|
|
1224
|
+
function normalizeValidationStrategy$1(value) {
|
|
1225
|
+
if (typeof value === 'string' && VALIDATION_STRATEGY_VALUES.includes(value)) {
|
|
1226
|
+
return value;
|
|
1227
|
+
}
|
|
1228
|
+
if (value != null && typeof value === 'object' && 'id' in value && typeof value.id === 'string') {
|
|
1229
|
+
return normalizeValidationStrategy$1(value.id);
|
|
1230
|
+
}
|
|
1231
|
+
return 'step';
|
|
1232
|
+
}
|
|
1233
|
+
/**
|
|
1234
|
+
* Coerces stored completion mode (string or SelectBox `{ id }`) to a known value.
|
|
1235
|
+
*/
|
|
1236
|
+
function normalizeCompletionMode(value) {
|
|
1237
|
+
if (typeof value === 'string' && COMPLETION_MODE_VALUES.includes(value)) {
|
|
1238
|
+
return value;
|
|
1239
|
+
}
|
|
1240
|
+
if (value != null && typeof value === 'object' && 'id' in value && typeof value.id === 'string') {
|
|
1241
|
+
return normalizeCompletionMode(value.id);
|
|
1242
|
+
}
|
|
1243
|
+
return 'submit-only';
|
|
1244
|
+
}
|
|
1245
|
+
/**
|
|
1246
|
+
* Maps entity `display` to {@link QuestionnaireDisplaySettings} (defaults when omitted).
|
|
1247
|
+
*/
|
|
1248
|
+
function toDisplaySettings(q) {
|
|
1249
|
+
if (!q) {
|
|
1250
|
+
return null;
|
|
1251
|
+
}
|
|
1252
|
+
const d = { ...DEFAULT_QUESTIONNAIRE_ENTITY_DISPLAY, ...q.display };
|
|
1253
|
+
return {
|
|
1254
|
+
viewMode: normalizeViewMode(d.viewMode),
|
|
1255
|
+
showProgressBar: d.showProgressBar ?? true,
|
|
1256
|
+
showTimer: d.showTimer ?? false,
|
|
1257
|
+
showQuestionNumbers: d.showQuestionNumbers ?? true,
|
|
1258
|
+
validationStrategy: normalizeValidationStrategy$1(d.validationStrategy),
|
|
1259
|
+
completionMode: normalizeCompletionMode(d.completionMode),
|
|
1260
|
+
};
|
|
1261
|
+
}
|
|
1262
|
+
//#endregion
|
|
1263
|
+
|
|
1001
1264
|
//#region ---- Pre/Post Content Utilities ----
|
|
1002
1265
|
/**
|
|
1003
1266
|
* Formats elapsed seconds as `m:ss` or `h:mm:ss` when an hour or more.
|
|
@@ -1015,7 +1278,7 @@ function formatElapsedDuration(totalSeconds) {
|
|
|
1015
1278
|
/**
|
|
1016
1279
|
* Resolve placeholders in summary content.
|
|
1017
1280
|
* Fixed: {{totalQuestions}}, {{answeredCount}}, {{totalTime}}, {{elapsedSeconds}}.
|
|
1018
|
-
* Plus any {{
|
|
1281
|
+
* Plus any {{outcomeName}} from values.outcomes.
|
|
1019
1282
|
*/
|
|
1020
1283
|
function resolveSummaryPlaceholders(content, values) {
|
|
1021
1284
|
if (!content)
|
|
@@ -1105,7 +1368,7 @@ function isQuestionnaireAnswerValueEmpty(value) {
|
|
|
1105
1368
|
//#endregion
|
|
1106
1369
|
//#region ---- Service ----
|
|
1107
1370
|
/**
|
|
1108
|
-
* Opens the questionnaire viewer dialog and evaluates questionnaire
|
|
1371
|
+
* Opens the questionnaire viewer dialog and evaluates questionnaire outcomes when a questionnaire id is provided.
|
|
1109
1372
|
*/
|
|
1110
1373
|
class AXMQuestionnaireViewerService {
|
|
1111
1374
|
constructor() {
|
|
@@ -1121,10 +1384,13 @@ class AXMQuestionnaireViewerService {
|
|
|
1121
1384
|
* Open questionnaire viewer in a dialog
|
|
1122
1385
|
*/
|
|
1123
1386
|
async open(config) {
|
|
1124
|
-
const { AXMQuestionnaireViewerPopupComponent } = await import('./acorex-modules-assessment-management-questionnaire-viewer-popup.component-
|
|
1387
|
+
const { AXMQuestionnaireViewerPopupComponent } = await import('./acorex-modules-assessment-management-questionnaire-viewer-popup.component-D9I3S-ZT.mjs');
|
|
1125
1388
|
const structure = config.structure;
|
|
1126
1389
|
const submitHandler = config.submitHandler ??
|
|
1127
|
-
((answers) => this.buildSummaryPlaceholderValues(structure, answers, {
|
|
1390
|
+
((answers) => this.buildSummaryPlaceholderValues(structure, answers, {
|
|
1391
|
+
questionnaireId: config.questionnaireId,
|
|
1392
|
+
outcomeRules: config.outcomeRules,
|
|
1393
|
+
}));
|
|
1128
1394
|
const result = await this.popupService.open(AXMQuestionnaireViewerPopupComponent, {
|
|
1129
1395
|
title: config.title,
|
|
1130
1396
|
size: this.deviceService.isSmall() ? 'full' : 'lg',
|
|
@@ -1137,17 +1403,19 @@ class AXMQuestionnaireViewerService {
|
|
|
1137
1403
|
saveHandler: config.saveHandler,
|
|
1138
1404
|
assessmentFillContext: config.assessmentFillContext,
|
|
1139
1405
|
questionnaireId: config.questionnaireId,
|
|
1406
|
+
outcomeRules: config.outcomeRules,
|
|
1407
|
+
storedOutcomeResults: config.storedOutcomeResults ?? null,
|
|
1140
1408
|
},
|
|
1141
1409
|
});
|
|
1142
1410
|
return result.data || null;
|
|
1143
1411
|
}
|
|
1144
1412
|
/**
|
|
1145
|
-
* Evaluate all questionnaire
|
|
1413
|
+
* Evaluate all questionnaire outcomes for the given questionnaire and answers.
|
|
1146
1414
|
* Pass `structure` so expressions can use `answer.byId`, `answer.byTag`, and `answer.allByTag`.
|
|
1147
1415
|
*/
|
|
1148
1416
|
/**
|
|
1149
1417
|
* Resolves `isVisible` for a section or question: `false` hides; `true`/undefined shows;
|
|
1150
|
-
* non-empty string is evaluated with the same scope as questionnaire
|
|
1418
|
+
* non-empty string is evaluated with the same scope as questionnaire outcomes (`answer.*`, `fn.*`, etc.).
|
|
1151
1419
|
*/
|
|
1152
1420
|
async evaluateQuestionnaireVisibilityFlag(isVisible, answers, structure) {
|
|
1153
1421
|
if (isVisible === false) {
|
|
@@ -1172,11 +1440,11 @@ class AXMQuestionnaireViewerService {
|
|
|
1172
1440
|
}
|
|
1173
1441
|
}
|
|
1174
1442
|
/**
|
|
1175
|
-
* Evaluates questionnaire
|
|
1443
|
+
* Evaluates questionnaire outcome rules and returns values plus display titles.
|
|
1176
1444
|
*/
|
|
1177
|
-
async evaluateOutcomes(
|
|
1178
|
-
const rules = await this.
|
|
1179
|
-
if (!rules
|
|
1445
|
+
async evaluateOutcomes(answers, options) {
|
|
1446
|
+
const rules = await this.resolveOutcomeRules(options?.questionnaireId, options?.outcomeRules);
|
|
1447
|
+
if (!rules.length)
|
|
1180
1448
|
return { values: {}, outcomeTitles: {} };
|
|
1181
1449
|
const sorted = this.topologicalSort(rules);
|
|
1182
1450
|
const outcomes = {};
|
|
@@ -1185,25 +1453,32 @@ class AXMQuestionnaireViewerService {
|
|
|
1185
1453
|
if (rule.name) {
|
|
1186
1454
|
outcomeTitles[rule.name] = this.resolveOutcomeDisplayTitle(rule);
|
|
1187
1455
|
}
|
|
1188
|
-
const value = await this.computeResult(rule, answers, outcomes, structure);
|
|
1456
|
+
const value = await this.computeResult(rule, answers, outcomes, options?.structure);
|
|
1189
1457
|
if (rule.name && value !== undefined)
|
|
1190
1458
|
outcomes[rule.name] = value;
|
|
1191
1459
|
}
|
|
1192
1460
|
return { values: outcomes, outcomeTitles };
|
|
1193
1461
|
}
|
|
1194
1462
|
/**
|
|
1195
|
-
* Progress metrics and optional
|
|
1463
|
+
* Progress metrics and optional outcome results for summary / preview.
|
|
1196
1464
|
*/
|
|
1197
1465
|
async buildSummaryPlaceholderValues(structure, answers, options) {
|
|
1198
1466
|
const { answeredQuestionsCount } = this.calculateProgressFromStructure(structure, answers);
|
|
1199
1467
|
const totalQuestions = structure?.sections?.reduce((s, sec) => s + (sec.items?.length ?? 0), 0) ?? 0;
|
|
1200
1468
|
let outcomes;
|
|
1201
1469
|
let outcomeTitles;
|
|
1202
|
-
|
|
1203
|
-
|
|
1470
|
+
let outcomeSections;
|
|
1471
|
+
if (options?.outcomeRules?.length || options?.questionnaireId) {
|
|
1472
|
+
const { values: evaluated, outcomeTitles: titles } = await this.evaluateOutcomes(answers, {
|
|
1473
|
+
questionnaireId: options?.questionnaireId,
|
|
1474
|
+
outcomeRules: options?.outcomeRules,
|
|
1475
|
+
structure,
|
|
1476
|
+
});
|
|
1204
1477
|
if (Object.keys(evaluated).length > 0) {
|
|
1205
1478
|
outcomes = evaluated;
|
|
1206
1479
|
outcomeTitles = titles;
|
|
1480
|
+
const sections = await this.resolveOutcomeSections(options?.questionnaireId, options?.outcomeRules);
|
|
1481
|
+
outcomeSections = this.buildOutcomeResultSections(sections, evaluated, titles);
|
|
1207
1482
|
}
|
|
1208
1483
|
}
|
|
1209
1484
|
const elapsed = options?.elapsedSeconds;
|
|
@@ -1215,6 +1490,30 @@ class AXMQuestionnaireViewerService {
|
|
|
1215
1490
|
totalTimeFormatted,
|
|
1216
1491
|
outcomes,
|
|
1217
1492
|
outcomeTitles,
|
|
1493
|
+
outcomeSections,
|
|
1494
|
+
};
|
|
1495
|
+
}
|
|
1496
|
+
/**
|
|
1497
|
+
* Builds outcome section rows from stored session values (no expression re-evaluation).
|
|
1498
|
+
*/
|
|
1499
|
+
async buildOutcomeResultsFromStoredValues(storedOutcomes, options) {
|
|
1500
|
+
const keys = Object.keys(storedOutcomes);
|
|
1501
|
+
if (!keys.length) {
|
|
1502
|
+
return { outcomes: {}, outcomeTitles: {}, outcomeSections: [] };
|
|
1503
|
+
}
|
|
1504
|
+
const rules = await this.resolveOutcomeRules(options.questionnaireId, undefined);
|
|
1505
|
+
const outcomeTitles = {};
|
|
1506
|
+
for (const rule of rules) {
|
|
1507
|
+
if (rule.name) {
|
|
1508
|
+
outcomeTitles[rule.name] = this.resolveOutcomeDisplayTitle(rule);
|
|
1509
|
+
}
|
|
1510
|
+
}
|
|
1511
|
+
const sections = await this.resolveOutcomeSections(options.questionnaireId, undefined);
|
|
1512
|
+
const outcomeSections = this.buildOutcomeResultSections(sections, storedOutcomes, outcomeTitles);
|
|
1513
|
+
return {
|
|
1514
|
+
outcomes: storedOutcomes,
|
|
1515
|
+
outcomeTitles,
|
|
1516
|
+
outcomeSections,
|
|
1218
1517
|
};
|
|
1219
1518
|
}
|
|
1220
1519
|
//#endregion
|
|
@@ -1246,38 +1545,100 @@ class AXMQuestionnaireViewerService {
|
|
|
1246
1545
|
return { answeredQuestionsCount: answered, progressPercentage };
|
|
1247
1546
|
}
|
|
1248
1547
|
//#endregion
|
|
1249
|
-
//#region ---- Questionnaire
|
|
1250
|
-
async
|
|
1251
|
-
|
|
1252
|
-
|
|
1548
|
+
//#region ---- Questionnaire outcomes (evaluation) ----
|
|
1549
|
+
async resolveOutcomeRules(questionnaireId, inlineRules) {
|
|
1550
|
+
if (inlineRules?.length) {
|
|
1551
|
+
return inlineRules;
|
|
1552
|
+
}
|
|
1553
|
+
if (!questionnaireId) {
|
|
1554
|
+
return [];
|
|
1555
|
+
}
|
|
1556
|
+
const questionnaire = await this.loadQuestionnaire(questionnaireId);
|
|
1557
|
+
return flattenQuestionnaireOutcomeItems(questionnaire?.outcomes);
|
|
1558
|
+
}
|
|
1559
|
+
async resolveOutcomeSections(questionnaireId, inlineRules) {
|
|
1560
|
+
if (inlineRules?.length) {
|
|
1561
|
+
return [{ name: 'outcomes', order: 0, items: inlineRules }];
|
|
1562
|
+
}
|
|
1563
|
+
if (!questionnaireId) {
|
|
1564
|
+
return [];
|
|
1565
|
+
}
|
|
1566
|
+
const questionnaire = await this.loadQuestionnaire(questionnaireId);
|
|
1567
|
+
return normalizeQuestionnaireOutcomesValue(questionnaire?.outcomes).sections;
|
|
1568
|
+
}
|
|
1569
|
+
async loadQuestionnaire(questionnaireId) {
|
|
1570
|
+
return this.entityService
|
|
1571
|
+
.withEntity(RootConfig.module.name, RootConfig.entities.questionnaire.name)
|
|
1253
1572
|
.data()
|
|
1254
|
-
.
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1573
|
+
.byKey(questionnaireId);
|
|
1574
|
+
}
|
|
1575
|
+
buildOutcomeResultSections(sections, values, titles) {
|
|
1576
|
+
const sortedSections = sections.slice().sort((a, b) => (a.order ?? 0) - (b.order ?? 0));
|
|
1577
|
+
const groups = [];
|
|
1578
|
+
for (const [index, section] of sortedSections.entries()) {
|
|
1579
|
+
const sectionName = (section.name ?? '').trim() || `section-${index + 1}`;
|
|
1580
|
+
const sectionOrder = section.order ?? index;
|
|
1581
|
+
const items = [];
|
|
1582
|
+
for (const item of section.items ?? []) {
|
|
1583
|
+
if (!item.name || values[item.name] === undefined) {
|
|
1584
|
+
continue;
|
|
1585
|
+
}
|
|
1586
|
+
const value = values[item.name];
|
|
1587
|
+
const display = this.resolveOutcomeDisplay(item, value);
|
|
1588
|
+
items.push({
|
|
1589
|
+
key: item.name,
|
|
1590
|
+
value,
|
|
1591
|
+
label: (titles[item.name] ?? '').trim() || this.humanizeOutcomeKey(item.name),
|
|
1592
|
+
display,
|
|
1593
|
+
});
|
|
1594
|
+
}
|
|
1595
|
+
if (items.length === 0) {
|
|
1596
|
+
continue;
|
|
1597
|
+
}
|
|
1598
|
+
groups.push({
|
|
1599
|
+
trackKey: `${sectionOrder}::${sectionName}`,
|
|
1600
|
+
sectionName,
|
|
1601
|
+
sectionOrder,
|
|
1602
|
+
sectionTitle: section.title ?? { 'en-US': sectionName },
|
|
1603
|
+
sectionDescription: section.description,
|
|
1604
|
+
items,
|
|
1605
|
+
});
|
|
1606
|
+
}
|
|
1607
|
+
return groups;
|
|
1608
|
+
}
|
|
1609
|
+
/**
|
|
1610
|
+
* First matching display rule for an evaluated outcome value.
|
|
1611
|
+
*/
|
|
1612
|
+
resolveOutcomeDisplay(rule, value) {
|
|
1613
|
+
const displayRules = normalizeQuestionnaireOutcomeDisplayRules(rule.displayRules);
|
|
1614
|
+
if (!displayRules.length) {
|
|
1615
|
+
return undefined;
|
|
1616
|
+
}
|
|
1617
|
+
for (const displayRule of displayRules) {
|
|
1618
|
+
if (matchesQuestionnaireOutcomeDisplayRule(value, displayRule)) {
|
|
1619
|
+
return {
|
|
1620
|
+
color: displayRule.color,
|
|
1621
|
+
emphasis: displayRule.emphasis ?? 'normal',
|
|
1622
|
+
iconClass: typeof displayRule.icon === 'string' ? displayRule.icon : undefined,
|
|
1623
|
+
};
|
|
1624
|
+
}
|
|
1625
|
+
}
|
|
1626
|
+
return undefined;
|
|
1264
1627
|
}
|
|
1265
1628
|
/**
|
|
1266
|
-
* Display label for
|
|
1629
|
+
* Display label for an outcome rule: `title` when set, otherwise a humanized `name`.
|
|
1267
1630
|
*/
|
|
1268
1631
|
resolveOutcomeDisplayTitle(rule) {
|
|
1269
|
-
const
|
|
1270
|
-
if (
|
|
1271
|
-
|
|
1272
|
-
if (t.length > 0)
|
|
1273
|
-
return t;
|
|
1632
|
+
const resolved = resolveMultiLanguageString(rule.title, 'en-US').trim();
|
|
1633
|
+
if (resolved.length > 0) {
|
|
1634
|
+
return resolved;
|
|
1274
1635
|
}
|
|
1275
1636
|
const name = rule.name?.trim();
|
|
1276
1637
|
if (name)
|
|
1277
|
-
return this.
|
|
1638
|
+
return this.humanizeOutcomeKey(name);
|
|
1278
1639
|
return '';
|
|
1279
1640
|
}
|
|
1280
|
-
|
|
1641
|
+
humanizeOutcomeKey(name) {
|
|
1281
1642
|
return name
|
|
1282
1643
|
.replace(/_/g, ' ')
|
|
1283
1644
|
.replace(/([a-z0-9])([A-Z])/g, '$1 $2')
|
|
@@ -1287,14 +1648,14 @@ class AXMQuestionnaireViewerService {
|
|
|
1287
1648
|
.join(' ');
|
|
1288
1649
|
}
|
|
1289
1650
|
async computeResult(rule, answers, outcomes, structure) {
|
|
1290
|
-
const exprText = this.
|
|
1651
|
+
const exprText = this.outcomeExpressionText(rule);
|
|
1291
1652
|
if (!exprText)
|
|
1292
1653
|
return undefined;
|
|
1293
1654
|
const raw = await this.evaluateOutcomeExpression(exprText, answers, outcomes, structure);
|
|
1294
1655
|
return this.coerceOutcome(raw, this.inferResultKind(rule));
|
|
1295
1656
|
}
|
|
1296
1657
|
/** Non-empty trimmed `expression`, or empty string if missing. */
|
|
1297
|
-
|
|
1658
|
+
outcomeExpressionText(rule) {
|
|
1298
1659
|
const exp = rule.expression;
|
|
1299
1660
|
return typeof exp === 'string' ? exp.trim() : '';
|
|
1300
1661
|
}
|
|
@@ -1332,17 +1693,17 @@ class AXMQuestionnaireViewerService {
|
|
|
1332
1693
|
return raw;
|
|
1333
1694
|
}
|
|
1334
1695
|
}
|
|
1335
|
-
async evaluateOutcomeExpression(expression, answers, outcomes, structure) {
|
|
1696
|
+
async evaluateOutcomeExpression(expression, answers, outcomes, structure, value) {
|
|
1336
1697
|
const trimmed = expression?.trim();
|
|
1337
1698
|
if (!trimmed)
|
|
1338
1699
|
return undefined;
|
|
1339
1700
|
try {
|
|
1340
|
-
const scope = this.buildExpressionScope(answers, outcomes, structure);
|
|
1701
|
+
const scope = this.buildExpressionScope(answers, outcomes, structure, value);
|
|
1341
1702
|
const wrapped = trimmed.includes('{{') ? trimmed : `{{ ${trimmed} }}`;
|
|
1342
1703
|
return await this.expressionEvaluator.evaluate(wrapped, scope);
|
|
1343
1704
|
}
|
|
1344
1705
|
catch (err) {
|
|
1345
|
-
console.warn('[QuestionnaireViewer]
|
|
1706
|
+
console.warn('[QuestionnaireViewer] Outcome expression evaluation failed:', expression, err);
|
|
1346
1707
|
return undefined;
|
|
1347
1708
|
}
|
|
1348
1709
|
}
|
|
@@ -1376,7 +1737,7 @@ class AXMQuestionnaireViewerService {
|
|
|
1376
1737
|
/**
|
|
1377
1738
|
* Scope: answer.eval (path), answer.byId / byTag / allByTag, formula.eval / outcome.eval, fn.* helpers.
|
|
1378
1739
|
*/
|
|
1379
|
-
buildExpressionScope(answers, outcomes, structure) {
|
|
1740
|
+
buildExpressionScope(answers, outcomes, structure, value) {
|
|
1380
1741
|
const resolveOutcome = (key) => outcomes[key];
|
|
1381
1742
|
const itemsOrdered = this.flattenQuestionnaireItems(structure ?? null);
|
|
1382
1743
|
const itemHasTag = (item, normalizedTag) => {
|
|
@@ -1472,6 +1833,7 @@ class AXMQuestionnaireViewerService {
|
|
|
1472
1833
|
formula: { eval: resolveOutcome },
|
|
1473
1834
|
outcome: { eval: resolveOutcome },
|
|
1474
1835
|
fn,
|
|
1836
|
+
...(value !== undefined ? { value } : {}),
|
|
1475
1837
|
};
|
|
1476
1838
|
}
|
|
1477
1839
|
expressionOutcomeRefs(expression, ruleNames) {
|
|
@@ -1513,7 +1875,7 @@ class AXMQuestionnaireViewerService {
|
|
|
1513
1875
|
visiting.add(name);
|
|
1514
1876
|
const rule = nameToRule.get(name);
|
|
1515
1877
|
if (rule) {
|
|
1516
|
-
const exprStr = this.
|
|
1878
|
+
const exprStr = this.outcomeExpressionText(rule);
|
|
1517
1879
|
const formDeps = this.expressionOutcomeRefs(exprStr, ruleNames);
|
|
1518
1880
|
for (const d of formDeps)
|
|
1519
1881
|
visit(d);
|
|
@@ -1531,13 +1893,2774 @@ class AXMQuestionnaireViewerService {
|
|
|
1531
1893
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMQuestionnaireViewerService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
1532
1894
|
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMQuestionnaireViewerService, providedIn: 'root' }); }
|
|
1533
1895
|
}
|
|
1534
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMQuestionnaireViewerService, decorators: [{
|
|
1535
|
-
type: Injectable,
|
|
1896
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMQuestionnaireViewerService, decorators: [{
|
|
1897
|
+
type: Injectable,
|
|
1898
|
+
args: [{
|
|
1899
|
+
providedIn: 'root',
|
|
1900
|
+
}]
|
|
1901
|
+
}] });
|
|
1902
|
+
|
|
1903
|
+
//#region ---- Imports ----
|
|
1904
|
+
//#endregion
|
|
1905
|
+
//#region ---- Groups ----
|
|
1906
|
+
const GROUP_IDENTITY = {
|
|
1907
|
+
name: 'identity',
|
|
1908
|
+
title: '@assessment-management:questionnaires.components.questionnaire-builder.groups.identity.title',
|
|
1909
|
+
order: 0,
|
|
1910
|
+
};
|
|
1911
|
+
const GROUP_VALIDATION = {
|
|
1912
|
+
name: 'validation',
|
|
1913
|
+
title: '@assessment-management:questionnaires.components.questionnaire-builder.groups.validation.title',
|
|
1914
|
+
order: 1,
|
|
1915
|
+
};
|
|
1916
|
+
const GROUP_VISIBILITY = {
|
|
1917
|
+
name: 'visibility',
|
|
1918
|
+
title: '@assessment-management:questionnaires.components.questionnaire-builder.groups.visibility.title',
|
|
1919
|
+
order: 2,
|
|
1920
|
+
};
|
|
1921
|
+
const GROUP_HINT = {
|
|
1922
|
+
name: 'hint',
|
|
1923
|
+
title: '@assessment-management:questionnaires.components.questionnaire-builder.groups.hint.title',
|
|
1924
|
+
order: 3,
|
|
1925
|
+
};
|
|
1926
|
+
const GROUP_COMMENT = {
|
|
1927
|
+
name: 'comment',
|
|
1928
|
+
title: '@assessment-management:questionnaires.components.questionnaire-builder.groups.comment.title',
|
|
1929
|
+
order: 4,
|
|
1930
|
+
};
|
|
1931
|
+
//#endregion
|
|
1932
|
+
//#region ---- Shared options ----
|
|
1933
|
+
const HINT_MODE_OPTIONS = [
|
|
1934
|
+
{
|
|
1935
|
+
id: 'off',
|
|
1936
|
+
title: '@assessment-management:questionnaires.components.questionnaire-builder.fields.hint-mode.options.off',
|
|
1937
|
+
},
|
|
1938
|
+
{
|
|
1939
|
+
id: 'info',
|
|
1940
|
+
title: '@assessment-management:questionnaires.components.questionnaire-builder.fields.hint-mode.options.info',
|
|
1941
|
+
},
|
|
1942
|
+
{
|
|
1943
|
+
id: 'warning',
|
|
1944
|
+
title: '@assessment-management:questionnaires.components.questionnaire-builder.fields.hint-mode.options.warning',
|
|
1945
|
+
},
|
|
1946
|
+
{
|
|
1947
|
+
id: 'danger',
|
|
1948
|
+
title: '@assessment-management:questionnaires.components.questionnaire-builder.fields.hint-mode.options.danger',
|
|
1949
|
+
},
|
|
1950
|
+
{
|
|
1951
|
+
id: 'success',
|
|
1952
|
+
title: '@assessment-management:questionnaires.components.questionnaire-builder.fields.hint-mode.options.success',
|
|
1953
|
+
},
|
|
1954
|
+
{
|
|
1955
|
+
id: 'neutral',
|
|
1956
|
+
title: '@assessment-management:questionnaires.components.questionnaire-builder.fields.hint-mode.options.neutral',
|
|
1957
|
+
},
|
|
1958
|
+
];
|
|
1959
|
+
//#endregion
|
|
1960
|
+
//#region ---- Properties by group ----
|
|
1961
|
+
const IDENTITY_PROPS = [
|
|
1962
|
+
{
|
|
1963
|
+
name: 'name',
|
|
1964
|
+
title: '@general:terms.common.name',
|
|
1965
|
+
group: GROUP_IDENTITY,
|
|
1966
|
+
order: 10,
|
|
1967
|
+
schema: {
|
|
1968
|
+
dataType: 'string',
|
|
1969
|
+
defaultValue: '',
|
|
1970
|
+
interface: {
|
|
1971
|
+
name: 'name',
|
|
1972
|
+
path: 'name',
|
|
1973
|
+
type: AXPWidgetsCatalog.text,
|
|
1974
|
+
options: {
|
|
1975
|
+
placeholder: '@general:terms.common.name',
|
|
1976
|
+
},
|
|
1977
|
+
},
|
|
1978
|
+
},
|
|
1979
|
+
visible: true,
|
|
1980
|
+
},
|
|
1981
|
+
{
|
|
1982
|
+
name: 'tags',
|
|
1983
|
+
title: '@assessment-management:questionnaires.components.questionnaire-builder.fields.tags.title',
|
|
1984
|
+
group: GROUP_IDENTITY,
|
|
1985
|
+
order: 20,
|
|
1986
|
+
schema: {
|
|
1987
|
+
dataType: 'array',
|
|
1988
|
+
defaultValue: [],
|
|
1989
|
+
interface: {
|
|
1990
|
+
name: 'tags',
|
|
1991
|
+
path: 'tags',
|
|
1992
|
+
type: 'tag-editor',
|
|
1993
|
+
options: {
|
|
1994
|
+
placeholder: '@assessment-management:questionnaires.components.questionnaire-builder.fields.tags.placeholder',
|
|
1995
|
+
allowDuplicate: false,
|
|
1996
|
+
},
|
|
1997
|
+
},
|
|
1998
|
+
},
|
|
1999
|
+
visible: true,
|
|
2000
|
+
},
|
|
2001
|
+
];
|
|
2002
|
+
const VALIDATION_PROPS = [
|
|
2003
|
+
{
|
|
2004
|
+
...createBooleanProperty({
|
|
2005
|
+
name: 'isRequired',
|
|
2006
|
+
path: 'isRequired',
|
|
2007
|
+
title: '@assessment-management:questionnaires.components.questionnaire-builder.fields.is-required.title',
|
|
2008
|
+
group: GROUP_VALIDATION,
|
|
2009
|
+
defaultValue: false,
|
|
2010
|
+
}),
|
|
2011
|
+
order: 10,
|
|
2012
|
+
},
|
|
2013
|
+
];
|
|
2014
|
+
const VISIBILITY_PROPS = [
|
|
2015
|
+
{
|
|
2016
|
+
...createBooleanProperty({
|
|
2017
|
+
name: 'isVisible',
|
|
2018
|
+
path: 'isVisible',
|
|
2019
|
+
title: '@assessment-management:questionnaires.components.questionnaire-builder.fields.visible.title',
|
|
2020
|
+
group: GROUP_VISIBILITY,
|
|
2021
|
+
defaultValue: true,
|
|
2022
|
+
}),
|
|
2023
|
+
order: 10,
|
|
2024
|
+
},
|
|
2025
|
+
];
|
|
2026
|
+
const HINT_PROPS = [
|
|
2027
|
+
{
|
|
2028
|
+
name: 'hintMode',
|
|
2029
|
+
title: '@assessment-management:questionnaires.components.questionnaire-builder.fields.hint-mode.title',
|
|
2030
|
+
group: GROUP_HINT,
|
|
2031
|
+
order: 10,
|
|
2032
|
+
schema: {
|
|
2033
|
+
dataType: 'string',
|
|
2034
|
+
defaultValue: { id: 'off', title: HINT_MODE_OPTIONS[0].title },
|
|
2035
|
+
interface: {
|
|
2036
|
+
name: 'hintMode',
|
|
2037
|
+
path: 'hint.mode',
|
|
2038
|
+
type: AXPWidgetsCatalog.select,
|
|
2039
|
+
options: {
|
|
2040
|
+
valueField: 'id',
|
|
2041
|
+
textField: 'title',
|
|
2042
|
+
dataSource: [...HINT_MODE_OPTIONS],
|
|
2043
|
+
},
|
|
2044
|
+
},
|
|
2045
|
+
},
|
|
2046
|
+
visible: true,
|
|
2047
|
+
},
|
|
2048
|
+
{
|
|
2049
|
+
name: 'hintContent',
|
|
2050
|
+
title: '@assessment-management:questionnaires.components.questionnaire-builder.fields.hint.title',
|
|
2051
|
+
group: GROUP_HINT,
|
|
2052
|
+
order: 20,
|
|
2053
|
+
schema: {
|
|
2054
|
+
dataType: 'string',
|
|
2055
|
+
defaultValue: '',
|
|
2056
|
+
interface: {
|
|
2057
|
+
name: 'hintContent',
|
|
2058
|
+
path: 'hint.content',
|
|
2059
|
+
type: AXPWidgetsCatalog.richText,
|
|
2060
|
+
options: {},
|
|
2061
|
+
},
|
|
2062
|
+
},
|
|
2063
|
+
visible: "{{ context.eval('hint.mode') && (context.eval('hint.mode').id || context.eval('hint.mode')) != 'off' }}",
|
|
2064
|
+
},
|
|
2065
|
+
];
|
|
2066
|
+
const COMMENT_PROPS = [
|
|
2067
|
+
{
|
|
2068
|
+
...createBooleanProperty({
|
|
2069
|
+
name: 'commentEnabled',
|
|
2070
|
+
path: 'comment.enabled',
|
|
2071
|
+
title: '@assessment-management:questionnaires.components.questionnaire-builder.fields.comment-enabled.title',
|
|
2072
|
+
group: GROUP_COMMENT,
|
|
2073
|
+
defaultValue: false,
|
|
2074
|
+
}),
|
|
2075
|
+
order: 10,
|
|
2076
|
+
},
|
|
2077
|
+
{
|
|
2078
|
+
...createBooleanProperty({
|
|
2079
|
+
name: 'commentRequired',
|
|
2080
|
+
path: 'comment.required',
|
|
2081
|
+
title: '@assessment-management:questionnaires.components.questionnaire-builder.fields.comment-required.title',
|
|
2082
|
+
group: GROUP_COMMENT,
|
|
2083
|
+
defaultValue: false,
|
|
2084
|
+
visible: "{{ context.eval('comment.enabled') === true }}",
|
|
2085
|
+
}),
|
|
2086
|
+
order: 20,
|
|
2087
|
+
},
|
|
2088
|
+
];
|
|
2089
|
+
//#endregion
|
|
2090
|
+
//#region ---- Hint form context helper ----
|
|
2091
|
+
/**
|
|
2092
|
+
* Builds initial `hint` object for the question property viewer from the effective (merged) hint config.
|
|
2093
|
+
*/
|
|
2094
|
+
function createQuestionHintFormContext(hint) {
|
|
2095
|
+
let content = '';
|
|
2096
|
+
if (hint.mode !== 'off') {
|
|
2097
|
+
const hc = hint.content;
|
|
2098
|
+
if (typeof hc === 'string') {
|
|
2099
|
+
content = hc;
|
|
2100
|
+
}
|
|
2101
|
+
else if (hc && typeof hc === 'object') {
|
|
2102
|
+
content = Object.values(hc)[0] ?? '';
|
|
2103
|
+
}
|
|
2104
|
+
}
|
|
2105
|
+
const modeId = hint.mode;
|
|
2106
|
+
const opt = HINT_MODE_OPTIONS.find((o) => o.id === modeId) ?? HINT_MODE_OPTIONS[0];
|
|
2107
|
+
return {
|
|
2108
|
+
content,
|
|
2109
|
+
mode: { id: opt.id, title: opt.title },
|
|
2110
|
+
};
|
|
2111
|
+
}
|
|
2112
|
+
//#endregion
|
|
2113
|
+
//#region ---- Tab definition ----
|
|
2114
|
+
/**
|
|
2115
|
+
* Property viewer tabs for editing a single questionnaire question row (metadata).
|
|
2116
|
+
*/
|
|
2117
|
+
const QUESTIONNAIRE_QUESTION_EDIT_TABS = [
|
|
2118
|
+
{
|
|
2119
|
+
name: 'general',
|
|
2120
|
+
title: '@assessment-management:questionnaires.components.questionnaire-builder.tabs.general.title',
|
|
2121
|
+
groups: [
|
|
2122
|
+
{
|
|
2123
|
+
name: GROUP_IDENTITY.name,
|
|
2124
|
+
title: GROUP_IDENTITY.title,
|
|
2125
|
+
isCollapsed: false,
|
|
2126
|
+
props: IDENTITY_PROPS,
|
|
2127
|
+
},
|
|
2128
|
+
{
|
|
2129
|
+
name: GROUP_VALIDATION.name,
|
|
2130
|
+
title: GROUP_VALIDATION.title,
|
|
2131
|
+
isCollapsed: false,
|
|
2132
|
+
props: VALIDATION_PROPS,
|
|
2133
|
+
},
|
|
2134
|
+
{
|
|
2135
|
+
name: GROUP_VISIBILITY.name,
|
|
2136
|
+
title: GROUP_VISIBILITY.title,
|
|
2137
|
+
isCollapsed: false,
|
|
2138
|
+
props: VISIBILITY_PROPS,
|
|
2139
|
+
},
|
|
2140
|
+
{
|
|
2141
|
+
name: GROUP_HINT.name,
|
|
2142
|
+
title: GROUP_HINT.title,
|
|
2143
|
+
isCollapsed: false,
|
|
2144
|
+
props: HINT_PROPS,
|
|
2145
|
+
},
|
|
2146
|
+
{
|
|
2147
|
+
name: GROUP_COMMENT.name,
|
|
2148
|
+
title: GROUP_COMMENT.title,
|
|
2149
|
+
isCollapsed: false,
|
|
2150
|
+
props: COMMENT_PROPS,
|
|
2151
|
+
},
|
|
2152
|
+
],
|
|
2153
|
+
},
|
|
2154
|
+
];
|
|
2155
|
+
//#endregion
|
|
2156
|
+
|
|
2157
|
+
//#region ---- Imports ----
|
|
2158
|
+
//#endregion
|
|
2159
|
+
//#region ---- Component ----
|
|
2160
|
+
/**
|
|
2161
|
+
* Reusable Questionnaire Builder Component
|
|
2162
|
+
* Can be used both in dialog and inline contexts
|
|
2163
|
+
*/
|
|
2164
|
+
class AXMQuestionnaireQuestionsBuilderComponent {
|
|
2165
|
+
//#endregion
|
|
2166
|
+
//#region ---- Question bank entity data ----
|
|
2167
|
+
questionBankData() {
|
|
2168
|
+
return this.entityService
|
|
2169
|
+
.withEntity(RootConfig.module.name, RootConfig.entities.questionBankItem.name)
|
|
2170
|
+
.data();
|
|
2171
|
+
}
|
|
2172
|
+
questionBankCategoryData() {
|
|
2173
|
+
return this.entityService
|
|
2174
|
+
.withEntity(RootConfig.module.name, `${RootConfig.entities.questionBankItem.name}Category`)
|
|
2175
|
+
.data();
|
|
2176
|
+
}
|
|
2177
|
+
//#endregion
|
|
2178
|
+
//#region ---- Lifecycle ----
|
|
2179
|
+
constructor() {
|
|
2180
|
+
//#region ---- Services & Dependencies ----
|
|
2181
|
+
this.dataSelectorService = inject(AXPDataSelectorService);
|
|
2182
|
+
this.entityService = inject(AXPEntityService);
|
|
2183
|
+
this.entityResolver = inject(AXPEntityDefinitionRegistryService);
|
|
2184
|
+
this.translationService = inject(AXTranslationService);
|
|
2185
|
+
this.propertyViewerService = inject(AXPPropertyViewerService);
|
|
2186
|
+
this.questionnaireViewerService = inject(AXMQuestionnaireViewerService);
|
|
2187
|
+
this.toastService = inject(AXToastService);
|
|
2188
|
+
this.widgetRegistry = inject(AXPWidgetRegistryService);
|
|
2189
|
+
this.commandService = inject(AXPCommandService);
|
|
2190
|
+
//#endregion
|
|
2191
|
+
//#region ---- Inputs & Outputs ----
|
|
2192
|
+
/**
|
|
2193
|
+
* Initial value (QuestionnaireBuilderValue)
|
|
2194
|
+
*/
|
|
2195
|
+
this.value = input(null, ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
|
|
2196
|
+
/**
|
|
2197
|
+
* Readonly mode
|
|
2198
|
+
*/
|
|
2199
|
+
this.readonly = input(false, ...(ngDevMode ? [{ debugName: "readonly" }] : /* istanbul ignore next */ []));
|
|
2200
|
+
/**
|
|
2201
|
+
* Pre/post config for preview (welcome, review, summary).
|
|
2202
|
+
* When provided, passed to the preview dialog.
|
|
2203
|
+
*/
|
|
2204
|
+
this.prePostConfig = input(null, ...(ngDevMode ? [{ debugName: "prePostConfig" }] : /* istanbul ignore next */ []));
|
|
2205
|
+
/**
|
|
2206
|
+
* When false, the header (Add Section, Settings, Preview, Full Screen) is hidden.
|
|
2207
|
+
* Use when actions are provided by the host (e.g. page primary header actions).
|
|
2208
|
+
*/
|
|
2209
|
+
this.showHeader = input(true, ...(ngDevMode ? [{ debugName: "showHeader" }] : /* istanbul ignore next */ []));
|
|
2210
|
+
/**
|
|
2211
|
+
* Display settings (view mode, progress bar, timer, etc.) when provided by the host (e.g. entity form).
|
|
2212
|
+
* Used for preview. When not provided, falls back to state/value or defaults.
|
|
2213
|
+
*/
|
|
2214
|
+
this.displaySettingsInput = input(null, ...(ngDevMode ? [{ debugName: "displaySettingsInput" }] : /* istanbul ignore next */ []));
|
|
2215
|
+
/**
|
|
2216
|
+
* Persisted questionnaire id (e.g. from entity form) — enables questionnaire outcomes in preview.
|
|
2217
|
+
*/
|
|
2218
|
+
this.questionnaireEntityId = input(undefined, ...(ngDevMode ? [{ debugName: "questionnaireEntityId" }] : /* istanbul ignore next */ []));
|
|
2219
|
+
/**
|
|
2220
|
+
* Value change event
|
|
2221
|
+
*/
|
|
2222
|
+
this.valueChange = output();
|
|
2223
|
+
//#endregion
|
|
2224
|
+
//#region ---- Class Properties ----
|
|
2225
|
+
// Designer state management - always start with at least one default section
|
|
2226
|
+
this.builderState = signal({
|
|
2227
|
+
sections: [createDefaultSection()],
|
|
2228
|
+
}, ...(ngDevMode ? [{ debugName: "builderState" }] : /* istanbul ignore next */ []));
|
|
2229
|
+
// Selected item tracking
|
|
2230
|
+
this.selectedItemName = signal(null, ...(ngDevMode ? [{ debugName: "selectedItemName" }] : /* istanbul ignore next */ []));
|
|
2231
|
+
this.selectedSectionName = signal(null, ...(ngDevMode ? [{ debugName: "selectedSectionName" }] : /* istanbul ignore next */ []));
|
|
2232
|
+
// Fullscreen directive reference
|
|
2233
|
+
this.fullscreenDirective = viewChild('fullscreen', ...(ngDevMode ? [{ debugName: "fullscreenDirective" }] : /* istanbul ignore next */ []));
|
|
2234
|
+
this.standardRef = viewChild(AXPStandardSectionItemsBuilderComponent, ...(ngDevMode ? [{ debugName: "standardRef" }] : /* istanbul ignore next */ []));
|
|
2235
|
+
//#endregion
|
|
2236
|
+
//#region ---- Computed Properties ----
|
|
2237
|
+
/** Value for {@link AXPStandardSectionItemsBuilderComponent} (sections only; drag/reorder handled there). */
|
|
2238
|
+
this.builderValue = computed(() => ({
|
|
2239
|
+
sections: this.builderState().sections.map((s) => ({
|
|
2240
|
+
id: s.name,
|
|
2241
|
+
name: s.name,
|
|
2242
|
+
order: s.order,
|
|
2243
|
+
title: s.title,
|
|
2244
|
+
description: s.description,
|
|
2245
|
+
tags: s.tags,
|
|
2246
|
+
isVisible: s.isVisible,
|
|
2247
|
+
items: s.items.map((it) => ({
|
|
2248
|
+
id: it.name,
|
|
2249
|
+
name: it.name,
|
|
2250
|
+
order: it.order,
|
|
2251
|
+
questionBankItemId: it.questionBankItemId,
|
|
2252
|
+
isRequired: it.isRequired,
|
|
2253
|
+
isVisible: it.isVisible,
|
|
2254
|
+
interfaceOverride: it.interfaceOverride,
|
|
2255
|
+
hint: it.hint,
|
|
2256
|
+
comment: it.comment,
|
|
2257
|
+
tags: it.tags,
|
|
2258
|
+
question: it.question,
|
|
2259
|
+
isNewlyAdded: it.isNewlyAdded,
|
|
2260
|
+
})),
|
|
2261
|
+
})),
|
|
2262
|
+
}), ...(ngDevMode ? [{ debugName: "builderValue" }] : /* istanbul ignore next */ []));
|
|
2263
|
+
this.isPreviewDisabled = computed(() => this.builderState().sections.length === 0 || this.builderState().sections.every((s) => s.items.length === 0), ...(ngDevMode ? [{ debugName: "isPreviewDisabled" }] : /* istanbul ignore next */ []));
|
|
2264
|
+
this.standardConfig = computed(() => ({
|
|
2265
|
+
showSectionTechnicalName: true,
|
|
2266
|
+
minSectionCount: 1,
|
|
2267
|
+
texts: {
|
|
2268
|
+
addSection: '@assessment-management:questionnaires.components.questionnaire-builder.actions.add-section.title',
|
|
2269
|
+
addItem: '@assessment-management:questionnaires.components.questionnaire-builder.actions.add-question.title',
|
|
2270
|
+
emptySectionsTitle: '@assessment-management:questionnaires.components.questionnaire-builder.empty-states.no-sections.title',
|
|
2271
|
+
emptySectionsDescription: '@assessment-management:questionnaires.components.questionnaire-builder.empty-states.no-sections.description',
|
|
2272
|
+
emptyItemsTitle: '@assessment-management:questionnaires.components.questionnaire-builder.empty-states.empty-section.title',
|
|
2273
|
+
emptyItemsDescription: '@assessment-management:questionnaires.components.questionnaire-builder.empty-states.empty-section.description',
|
|
2274
|
+
defaultSectionBadge: '@assessment-management:questionnaires.components.questionnaire-builder.default-section-badge',
|
|
2275
|
+
},
|
|
2276
|
+
mapItemToView: (item, section) => this.mapQuestionnaireItemToView(item, section),
|
|
2277
|
+
promptAddItems: (sid, v) => this.questionnairePromptAddItems(sid, v),
|
|
2278
|
+
promptEditItem: (item, sid, v) => this.questionnairePromptEditItem(item, sid, v),
|
|
2279
|
+
}), ...(ngDevMode ? [{ debugName: "standardConfig" }] : /* istanbul ignore next */ []));
|
|
2280
|
+
/**
|
|
2281
|
+
* Get current display settings from state or default
|
|
2282
|
+
*/
|
|
2283
|
+
this.displaySettings = computed(() => {
|
|
2284
|
+
const fromInput = this.displaySettingsInput();
|
|
2285
|
+
if (fromInput != null) {
|
|
2286
|
+
return fromInput;
|
|
2287
|
+
}
|
|
2288
|
+
const state = this.builderState();
|
|
2289
|
+
if (state.displaySettings) {
|
|
2290
|
+
return state.displaySettings;
|
|
2291
|
+
}
|
|
2292
|
+
const currentValue = convertStateToValue(state, this.value() || undefined);
|
|
2293
|
+
return (currentValue.displaySettings || {
|
|
2294
|
+
viewMode: 'single-page',
|
|
2295
|
+
showProgressBar: true,
|
|
2296
|
+
showTimer: false,
|
|
2297
|
+
showQuestionNumbers: true,
|
|
2298
|
+
});
|
|
2299
|
+
}, ...(ngDevMode ? [{ debugName: "displaySettings" }] : /* istanbul ignore next */ []));
|
|
2300
|
+
// Track last emitted value to prevent circular updates
|
|
2301
|
+
let lastEmittedValue = null;
|
|
2302
|
+
// Sync value input to state (only when value changes externally)
|
|
2303
|
+
effect(() => {
|
|
2304
|
+
const val = this.value();
|
|
2305
|
+
if (val !== null && val !== undefined) {
|
|
2306
|
+
const currentState = untracked(() => this.builderState());
|
|
2307
|
+
const currentValue = convertStateToValue(currentState);
|
|
2308
|
+
const valStr = JSON.stringify(val);
|
|
2309
|
+
const currentStr = JSON.stringify(currentValue);
|
|
2310
|
+
const lastEmittedStr = lastEmittedValue ? JSON.stringify(lastEmittedValue) : null;
|
|
2311
|
+
if (valStr !== currentStr && valStr !== lastEmittedStr) {
|
|
2312
|
+
const newState = convertValueToState(val);
|
|
2313
|
+
untracked(() => {
|
|
2314
|
+
this.builderState.set(newState);
|
|
2315
|
+
this.loadQuestionDetailsForState(newState);
|
|
2316
|
+
});
|
|
2317
|
+
}
|
|
2318
|
+
}
|
|
2319
|
+
else if (val === null || val === undefined) {
|
|
2320
|
+
// If value is null/undefined, ensure we have at least one default section
|
|
2321
|
+
const currentState = untracked(() => this.builderState());
|
|
2322
|
+
if (currentState.sections.length === 0) {
|
|
2323
|
+
const defaultSection = createDefaultSection();
|
|
2324
|
+
defaultSection.order = 0;
|
|
2325
|
+
untracked(() => {
|
|
2326
|
+
this.builderState.set({ sections: [defaultSection] });
|
|
2327
|
+
});
|
|
2328
|
+
}
|
|
2329
|
+
}
|
|
2330
|
+
});
|
|
2331
|
+
// Sync state changes to output
|
|
2332
|
+
effect(() => {
|
|
2333
|
+
const state = this.builderState();
|
|
2334
|
+
const currentValue = this.value();
|
|
2335
|
+
const value = convertStateToValue(state, currentValue || undefined);
|
|
2336
|
+
untracked(() => {
|
|
2337
|
+
lastEmittedValue = value;
|
|
2338
|
+
this.valueChange.emit(value);
|
|
2339
|
+
});
|
|
2340
|
+
});
|
|
2341
|
+
}
|
|
2342
|
+
/**
|
|
2343
|
+
* Load question details for all items in the state
|
|
2344
|
+
*/
|
|
2345
|
+
async loadQuestionDetailsForState(state) {
|
|
2346
|
+
const questionIds = new Set();
|
|
2347
|
+
// Collect all question bank item IDs
|
|
2348
|
+
state.sections.forEach((section) => {
|
|
2349
|
+
section.items.forEach((item) => {
|
|
2350
|
+
if (item.questionBankItemId && !item.question) {
|
|
2351
|
+
questionIds.add(item.questionBankItemId);
|
|
2352
|
+
}
|
|
2353
|
+
});
|
|
2354
|
+
});
|
|
2355
|
+
if (questionIds.size === 0)
|
|
2356
|
+
return;
|
|
2357
|
+
// Load all questions in parallel
|
|
2358
|
+
const questionPromises = Array.from(questionIds).map((id) => this.questionBankData()
|
|
2359
|
+
.byKey(id)
|
|
2360
|
+
.catch(() => null));
|
|
2361
|
+
const questions = await Promise.all(questionPromises);
|
|
2362
|
+
// Create a map of question ID to question data
|
|
2363
|
+
const questionMap = new Map();
|
|
2364
|
+
questions.forEach((q) => {
|
|
2365
|
+
if (q) {
|
|
2366
|
+
questionMap.set(q.id, q);
|
|
2367
|
+
}
|
|
2368
|
+
});
|
|
2369
|
+
// Update state with question details
|
|
2370
|
+
this.builderState.update((currentState) => ({
|
|
2371
|
+
...currentState,
|
|
2372
|
+
sections: currentState.sections.map((section) => ({
|
|
2373
|
+
...section,
|
|
2374
|
+
items: section.items.map((item) => {
|
|
2375
|
+
if (item.question)
|
|
2376
|
+
return item; // Already has question data
|
|
2377
|
+
const questionData = questionMap.get(item.questionBankItemId);
|
|
2378
|
+
if (questionData) {
|
|
2379
|
+
return {
|
|
2380
|
+
...item,
|
|
2381
|
+
question: {
|
|
2382
|
+
id: questionData.id,
|
|
2383
|
+
title: questionData.title,
|
|
2384
|
+
question: questionData.question,
|
|
2385
|
+
note: questionData.note,
|
|
2386
|
+
difficulty: questionData.difficulty,
|
|
2387
|
+
interface: questionData.interface,
|
|
2388
|
+
},
|
|
2389
|
+
};
|
|
2390
|
+
}
|
|
2391
|
+
return item;
|
|
2392
|
+
}),
|
|
2393
|
+
})),
|
|
2394
|
+
}));
|
|
2395
|
+
}
|
|
2396
|
+
mapQuestionnaireItemToView(item, _section) {
|
|
2397
|
+
const q = item;
|
|
2398
|
+
const title = this.itemQuestionHeading(q);
|
|
2399
|
+
const note = this.itemQuestionNotePreview(q);
|
|
2400
|
+
const badges = [];
|
|
2401
|
+
const req = q.isRequired;
|
|
2402
|
+
const rawReq = typeof req === 'boolean' || typeof req === 'string' ? req : undefined;
|
|
2403
|
+
const requiredMode = getQuestionnaireItemRequiredBadgeMode(rawReq);
|
|
2404
|
+
if (requiredMode === 'required') {
|
|
2405
|
+
badges.push({
|
|
2406
|
+
text: '@assessment-management:questionnaires.components.questionnaire-builder.item-badge.required',
|
|
2407
|
+
variant: 'danger',
|
|
2408
|
+
});
|
|
2409
|
+
}
|
|
2410
|
+
else if (requiredMode === 'conditional') {
|
|
2411
|
+
badges.push({
|
|
2412
|
+
text: '@assessment-management:questionnaires.components.questionnaire-builder.item-badge.conditional-required',
|
|
2413
|
+
variant: 'warning',
|
|
2414
|
+
});
|
|
2415
|
+
}
|
|
2416
|
+
else {
|
|
2417
|
+
badges.push({
|
|
2418
|
+
text: '@assessment-management:questionnaires.components.questionnaire-builder.item-badge.optional',
|
|
2419
|
+
variant: 'success',
|
|
2420
|
+
});
|
|
2421
|
+
}
|
|
2422
|
+
const rawVis = q.isVisible;
|
|
2423
|
+
const visibilityMode = getQuestionnaireItemVisibilityBadgeMode(typeof rawVis === 'boolean' || typeof rawVis === 'string' ? rawVis : undefined);
|
|
2424
|
+
if (visibilityMode === 'hidden') {
|
|
2425
|
+
badges.push({
|
|
2426
|
+
text: '@assessment-management:questionnaires.components.questionnaire-builder.item-badge.visibility-hidden',
|
|
2427
|
+
variant: 'danger',
|
|
2428
|
+
});
|
|
2429
|
+
}
|
|
2430
|
+
else if (visibilityMode === 'conditional') {
|
|
2431
|
+
badges.push({
|
|
2432
|
+
text: '@assessment-management:questionnaires.components.questionnaire-builder.item-badge.visibility-conditional',
|
|
2433
|
+
variant: 'warning',
|
|
2434
|
+
});
|
|
2435
|
+
}
|
|
2436
|
+
else {
|
|
2437
|
+
badges.push({
|
|
2438
|
+
text: '@assessment-management:questionnaires.components.questionnaire-builder.item-badge.visibility-visible',
|
|
2439
|
+
variant: 'success',
|
|
2440
|
+
});
|
|
2441
|
+
}
|
|
2442
|
+
return {
|
|
2443
|
+
icon: this.getQuestionWidgetIcon(q),
|
|
2444
|
+
title,
|
|
2445
|
+
name: q.name,
|
|
2446
|
+
description: note || undefined,
|
|
2447
|
+
badges,
|
|
2448
|
+
};
|
|
2449
|
+
}
|
|
2450
|
+
/**
|
|
2451
|
+
* Standard section-items builder emits here. Uses direct `builderState.update` so the `valueChange`
|
|
2452
|
+
* effect runs in the same turn and hosts (e.g. questions page) can mark dirty.
|
|
2453
|
+
*/
|
|
2454
|
+
onBuilderValueChange(next) {
|
|
2455
|
+
this.builderState.update((state) => {
|
|
2456
|
+
const updatedState = {
|
|
2457
|
+
...state,
|
|
2458
|
+
sections: this.mergeSectionsFromStandardBuilder(next.sections, state.sections),
|
|
2459
|
+
};
|
|
2460
|
+
if (updatedState.sections.length === 0) {
|
|
2461
|
+
const defaultSection = createDefaultSection();
|
|
2462
|
+
defaultSection.order = 0;
|
|
2463
|
+
return { ...updatedState, sections: [defaultSection] };
|
|
2464
|
+
}
|
|
2465
|
+
return updatedState;
|
|
2466
|
+
});
|
|
2467
|
+
}
|
|
2468
|
+
mergeSectionsFromStandardBuilder(incoming, previous) {
|
|
2469
|
+
const prevByName = new Map(previous.map((s) => [s.name, s]));
|
|
2470
|
+
return incoming.map((sec) => {
|
|
2471
|
+
const axSec = sec;
|
|
2472
|
+
const incomingName = String(axSec['name'] ?? axSec['id'] ?? '').trim();
|
|
2473
|
+
const prevSec = prevByName.get(incomingName);
|
|
2474
|
+
if (!prevSec) {
|
|
2475
|
+
return this.normalizeIncomingSection(sec);
|
|
2476
|
+
}
|
|
2477
|
+
const prevItemByName = new Map(prevSec.items.map((i) => [i.name, i]));
|
|
2478
|
+
const merged = this.normalizeIncomingSection(sec);
|
|
2479
|
+
return {
|
|
2480
|
+
...merged,
|
|
2481
|
+
isNewlyAdded: prevSec.isNewlyAdded ?? merged.isNewlyAdded,
|
|
2482
|
+
items: merged.items.map((it) => {
|
|
2483
|
+
const prev = prevItemByName.get(it.name);
|
|
2484
|
+
if (!prev) {
|
|
2485
|
+
return it;
|
|
2486
|
+
}
|
|
2487
|
+
return {
|
|
2488
|
+
...prev,
|
|
2489
|
+
...it,
|
|
2490
|
+
question: it.question ?? prev.question,
|
|
2491
|
+
};
|
|
2492
|
+
}),
|
|
2493
|
+
};
|
|
2494
|
+
});
|
|
2495
|
+
}
|
|
2496
|
+
/** Map platform section rows (id + name) into domain sections (name only). */
|
|
2497
|
+
normalizeIncomingSection(sec) {
|
|
2498
|
+
const ax = sec;
|
|
2499
|
+
const name = String(ax['name'] ?? ax['id'] ?? '').trim() || `section-${Date.now()}`;
|
|
2500
|
+
return {
|
|
2501
|
+
name,
|
|
2502
|
+
title: sec.title,
|
|
2503
|
+
description: sec.description,
|
|
2504
|
+
order: sec.order,
|
|
2505
|
+
tags: sec.tags,
|
|
2506
|
+
isVisible: sec.isVisible,
|
|
2507
|
+
isNewlyAdded: sec.isNewlyAdded,
|
|
2508
|
+
items: sec.items.map((it) => this.normalizeIncomingItem(it)),
|
|
2509
|
+
};
|
|
2510
|
+
}
|
|
2511
|
+
normalizeIncomingItem(it) {
|
|
2512
|
+
const name = String(it['name'] ?? it['id'] ?? '').trim() || `item-${Date.now()}`;
|
|
2513
|
+
const qbi = it.questionBankItemId;
|
|
2514
|
+
return {
|
|
2515
|
+
name,
|
|
2516
|
+
questionBankItemId: qbi,
|
|
2517
|
+
order: it.order,
|
|
2518
|
+
isRequired: it.isRequired,
|
|
2519
|
+
isVisible: it.isVisible,
|
|
2520
|
+
interfaceOverride: it.interfaceOverride,
|
|
2521
|
+
hint: it.hint,
|
|
2522
|
+
comment: it.comment,
|
|
2523
|
+
tags: it.tags,
|
|
2524
|
+
question: it.question,
|
|
2525
|
+
isNewlyAdded: it.isNewlyAdded,
|
|
2526
|
+
};
|
|
2527
|
+
}
|
|
2528
|
+
/** Edit dialog context: default visible; normalize legacy string booleans; expressions pass through (property viewer handles binding). */
|
|
2529
|
+
questionEditFormIsVisible(raw) {
|
|
2530
|
+
if (raw === undefined || raw === null) {
|
|
2531
|
+
return true;
|
|
2532
|
+
}
|
|
2533
|
+
if (typeof raw === 'boolean') {
|
|
2534
|
+
return raw;
|
|
2535
|
+
}
|
|
2536
|
+
if (raw.trim() === '') {
|
|
2537
|
+
return true;
|
|
2538
|
+
}
|
|
2539
|
+
const t = raw.trim().toLowerCase();
|
|
2540
|
+
if (t === 'true' || t === '1') {
|
|
2541
|
+
return true;
|
|
2542
|
+
}
|
|
2543
|
+
if (t === 'false' || t === '0') {
|
|
2544
|
+
return false;
|
|
2545
|
+
}
|
|
2546
|
+
return raw.trim();
|
|
2547
|
+
}
|
|
2548
|
+
questionEditFormIsRequired(item) {
|
|
2549
|
+
const r = item.isRequired;
|
|
2550
|
+
if (typeof r === 'string') {
|
|
2551
|
+
const t = r.trim();
|
|
2552
|
+
if (!t) {
|
|
2553
|
+
return false;
|
|
2554
|
+
}
|
|
2555
|
+
const tl = t.toLowerCase();
|
|
2556
|
+
if (tl === 'true' || tl === '1') {
|
|
2557
|
+
return true;
|
|
2558
|
+
}
|
|
2559
|
+
if (tl === 'false' || tl === '0') {
|
|
2560
|
+
return false;
|
|
2561
|
+
}
|
|
2562
|
+
return t;
|
|
2563
|
+
}
|
|
2564
|
+
return r ?? false;
|
|
2565
|
+
}
|
|
2566
|
+
/** Persist from property viewer: omit when default visible; `false` when hidden; trimmed non-empty string = expression. */
|
|
2567
|
+
persistQuestionIsVisibleFromForm(value) {
|
|
2568
|
+
if (value === undefined || value === null) {
|
|
2569
|
+
return undefined;
|
|
2570
|
+
}
|
|
2571
|
+
if (typeof value === 'boolean') {
|
|
2572
|
+
return value ? undefined : false;
|
|
2573
|
+
}
|
|
2574
|
+
if (typeof value === 'string') {
|
|
2575
|
+
const t = value.trim();
|
|
2576
|
+
return t || undefined;
|
|
2577
|
+
}
|
|
2578
|
+
return undefined;
|
|
2579
|
+
}
|
|
2580
|
+
persistQuestionIsRequiredFromForm(value) {
|
|
2581
|
+
if (value === undefined || value === null) {
|
|
2582
|
+
return false;
|
|
2583
|
+
}
|
|
2584
|
+
if (typeof value === 'boolean') {
|
|
2585
|
+
return value;
|
|
2586
|
+
}
|
|
2587
|
+
if (typeof value === 'string') {
|
|
2588
|
+
const t = value.trim();
|
|
2589
|
+
if (!t) {
|
|
2590
|
+
return false;
|
|
2591
|
+
}
|
|
2592
|
+
return t;
|
|
2593
|
+
}
|
|
2594
|
+
return false;
|
|
2595
|
+
}
|
|
2596
|
+
async questionnairePromptEditItem(item, sectionId, _value) {
|
|
2597
|
+
const qItem = item;
|
|
2598
|
+
const validationFailed = async (titleKey, descKey, fallTitle, fallDesc) => {
|
|
2599
|
+
const title = (await this.translationService.translateAsync(titleKey)) || fallTitle;
|
|
2600
|
+
const content = (await this.translationService.translateAsync(descKey)) || fallDesc;
|
|
2601
|
+
this.toastService.show({ color: 'warning', title, content });
|
|
2602
|
+
throw new Error('QuestionnaireEditQuestionValidation');
|
|
2603
|
+
};
|
|
2604
|
+
try {
|
|
2605
|
+
const bankRow = qItem.questionBankItemId
|
|
2606
|
+
? await this.entityService
|
|
2607
|
+
.withEntity(RootConfig.module.name, RootConfig.entities.questionBankItem.name)
|
|
2608
|
+
.data()
|
|
2609
|
+
.byKey(qItem.questionBankItemId)
|
|
2610
|
+
.catch(() => null)
|
|
2611
|
+
: null;
|
|
2612
|
+
const bankComment = normalizeQuestionCommentConfig(bankRow?.comment);
|
|
2613
|
+
const mergedCommentForForm = mergeQuestionCommentConfig(bankComment, qItem.comment);
|
|
2614
|
+
const bankHint = normalizeQuestionHintFromEntityRow(bankRow ?? {});
|
|
2615
|
+
const mergedHintForForm = mergeQuestionHintForViewer(bankHint, parseQuestionHintPartialFromRecord(qItem));
|
|
2616
|
+
const result = await this.propertyViewerService
|
|
2617
|
+
.create()
|
|
2618
|
+
.dialog((d) => {
|
|
2619
|
+
d.setTitle('@assessment-management:questionnaires.components.questionnaire-builder.actions.edit-question.title')
|
|
2620
|
+
.setSize('md')
|
|
2621
|
+
.setCloseButton(true)
|
|
2622
|
+
.setMode('advanced')
|
|
2623
|
+
.setTabs(QUESTIONNAIRE_QUESTION_EDIT_TABS)
|
|
2624
|
+
.setContext({
|
|
2625
|
+
name: qItem.name,
|
|
2626
|
+
tags: qItem.tags ?? [],
|
|
2627
|
+
isRequired: this.questionEditFormIsRequired(qItem),
|
|
2628
|
+
isVisible: this.questionEditFormIsVisible(qItem.isVisible),
|
|
2629
|
+
hint: createQuestionHintFormContext(mergedHintForForm),
|
|
2630
|
+
comment: mergedCommentForForm,
|
|
2631
|
+
})
|
|
2632
|
+
.onAction(async (ref) => {
|
|
2633
|
+
const context = ref.context();
|
|
2634
|
+
const rawId = String(context.name ?? '').trim();
|
|
2635
|
+
if (!rawId) {
|
|
2636
|
+
await validationFailed('@assessment-management:questionnaires.components.questionnaire-builder.validation.question-id-required.title', '@assessment-management:questionnaires.components.questionnaire-builder.validation.question-id-required.description', 'Question ID required', 'Enter a unique question ID.');
|
|
2637
|
+
}
|
|
2638
|
+
if (!this.isValidQuestionnaireItemName(rawId)) {
|
|
2639
|
+
await validationFailed('@assessment-management:questionnaires.components.questionnaire-builder.validation.question-id-invalid.title', '@assessment-management:questionnaires.components.questionnaire-builder.validation.question-id-invalid.description', 'Invalid question ID', 'Use letters, numbers, underscores, and hyphens (1–128 characters).');
|
|
2640
|
+
}
|
|
2641
|
+
const isDuplicate = this.builderState().sections.some((s) => s.items.some((i) => (s.name !== sectionId || i.name !== qItem.name) && i.name === rawId));
|
|
2642
|
+
if (isDuplicate) {
|
|
2643
|
+
await validationFailed('@assessment-management:questionnaires.components.questionnaire-builder.validation.question-id-duplicate.title', '@assessment-management:questionnaires.components.questionnaire-builder.validation.question-id-duplicate.description', 'Duplicate question ID', 'Another question already uses this ID.');
|
|
2644
|
+
}
|
|
2645
|
+
});
|
|
2646
|
+
})
|
|
2647
|
+
.show();
|
|
2648
|
+
if (!result) {
|
|
2649
|
+
return null;
|
|
2650
|
+
}
|
|
2651
|
+
const formData = result.values;
|
|
2652
|
+
const rawIdOut = String(formData.name ?? '').trim();
|
|
2653
|
+
const tags = this.normalizeTagsFromForm(formData.tags);
|
|
2654
|
+
const hintPersist = this.persistQuestionHintFromForm(bankHint, formData.hint);
|
|
2655
|
+
const commentPersist = this.persistQuestionCommentFromForm(bankComment, formData.comment);
|
|
2656
|
+
const nextItem = {
|
|
2657
|
+
...qItem,
|
|
2658
|
+
name: rawIdOut,
|
|
2659
|
+
id: rawIdOut,
|
|
2660
|
+
tags,
|
|
2661
|
+
isRequired: this.persistQuestionIsRequiredFromForm(formData.isRequired),
|
|
2662
|
+
isVisible: this.persistQuestionIsVisibleFromForm(formData.isVisible),
|
|
2663
|
+
};
|
|
2664
|
+
if (hintPersist != null) {
|
|
2665
|
+
nextItem.hint = hintPersist;
|
|
2666
|
+
}
|
|
2667
|
+
else {
|
|
2668
|
+
delete nextItem.hint;
|
|
2669
|
+
}
|
|
2670
|
+
if (commentPersist != null) {
|
|
2671
|
+
nextItem.comment = commentPersist;
|
|
2672
|
+
}
|
|
2673
|
+
else {
|
|
2674
|
+
delete nextItem.comment;
|
|
2675
|
+
}
|
|
2676
|
+
return nextItem;
|
|
2677
|
+
}
|
|
2678
|
+
catch (error) {
|
|
2679
|
+
if (error instanceof Error && error.message === 'QuestionnaireEditQuestionValidation') {
|
|
2680
|
+
return null;
|
|
2681
|
+
}
|
|
2682
|
+
console.error('Error editing question:', error);
|
|
2683
|
+
return null;
|
|
2684
|
+
}
|
|
2685
|
+
}
|
|
2686
|
+
//#endregion
|
|
2687
|
+
//#region ---- Section Management ----
|
|
2688
|
+
/** Toolbar / page command: delegates to {@link AXPStandardSectionItemsBuilderComponent#addSection}. */
|
|
2689
|
+
async addSection() {
|
|
2690
|
+
await this.standardRef()?.addSection();
|
|
2691
|
+
}
|
|
2692
|
+
//#endregion
|
|
2693
|
+
//#region ---- Item Management ----
|
|
2694
|
+
async questionnairePromptAddItems(sectionId, value) {
|
|
2695
|
+
const all = value.sections;
|
|
2696
|
+
const section = all.find((x) => x.name === sectionId);
|
|
2697
|
+
if (!section)
|
|
2698
|
+
return null;
|
|
2699
|
+
return (await this.selectQuestionsFromQuestionBankForSection(section, all));
|
|
2700
|
+
}
|
|
2701
|
+
/**
|
|
2702
|
+
* Open question bank selector and return new items (standard builder appends them).
|
|
2703
|
+
*/
|
|
2704
|
+
async selectQuestionsFromQuestionBankForSection(section, allSections) {
|
|
2705
|
+
try {
|
|
2706
|
+
const dataSource = new AXDataSource({
|
|
2707
|
+
key: 'id',
|
|
2708
|
+
pageSize: 20,
|
|
2709
|
+
load: async (e) => {
|
|
2710
|
+
const questions = await this.questionBankData().query(e);
|
|
2711
|
+
return {
|
|
2712
|
+
items: questions.items,
|
|
2713
|
+
total: questions.total,
|
|
2714
|
+
};
|
|
2715
|
+
},
|
|
2716
|
+
});
|
|
2717
|
+
// Create category tree data source for filtering
|
|
2718
|
+
const categoryTreeDataSource = {
|
|
2719
|
+
loadRootNodes: async () => {
|
|
2720
|
+
const result = await this.questionBankCategoryData().query({
|
|
2721
|
+
skip: 0,
|
|
2722
|
+
take: 1000,
|
|
2723
|
+
filter: {
|
|
2724
|
+
field: 'parentId',
|
|
2725
|
+
operator: { type: 'isEmpty' },
|
|
2726
|
+
value: true,
|
|
2727
|
+
},
|
|
2728
|
+
});
|
|
2729
|
+
return result.items.map((item) => ({
|
|
2730
|
+
id: item.id,
|
|
2731
|
+
title: item.title || item.name,
|
|
2732
|
+
description: item.description || '',
|
|
2733
|
+
parentId: item.parentId,
|
|
2734
|
+
childrenCount: item.childrenCount || 0,
|
|
2735
|
+
}));
|
|
2736
|
+
},
|
|
2737
|
+
loadChildNodes: async (parentId) => {
|
|
2738
|
+
const result = await this.questionBankCategoryData().query({
|
|
2739
|
+
skip: 0,
|
|
2740
|
+
take: 1000,
|
|
2741
|
+
filter: {
|
|
2742
|
+
field: 'parentId',
|
|
2743
|
+
operator: { type: 'equal' },
|
|
2744
|
+
value: parentId,
|
|
2745
|
+
},
|
|
2746
|
+
});
|
|
2747
|
+
return result.items.map((item) => ({
|
|
2748
|
+
id: item.id,
|
|
2749
|
+
title: item.title || item.name,
|
|
2750
|
+
description: item.description || '',
|
|
2751
|
+
parentId: item.parentId,
|
|
2752
|
+
childrenCount: item.childrenCount || 0,
|
|
2753
|
+
}));
|
|
2754
|
+
},
|
|
2755
|
+
searchNodes: async (searchValue) => {
|
|
2756
|
+
const result = await this.questionBankCategoryData().query({
|
|
2757
|
+
skip: 0,
|
|
2758
|
+
take: 1000,
|
|
2759
|
+
filter: {
|
|
2760
|
+
filters: [
|
|
2761
|
+
{
|
|
2762
|
+
field: 'title',
|
|
2763
|
+
operator: { type: 'contains' },
|
|
2764
|
+
value: searchValue,
|
|
2765
|
+
},
|
|
2766
|
+
{
|
|
2767
|
+
field: 'name',
|
|
2768
|
+
operator: { type: 'contains' },
|
|
2769
|
+
value: searchValue,
|
|
2770
|
+
},
|
|
2771
|
+
],
|
|
2772
|
+
logic: 'or',
|
|
2773
|
+
},
|
|
2774
|
+
});
|
|
2775
|
+
return result.items.map((item) => ({
|
|
2776
|
+
id: item.id,
|
|
2777
|
+
title: item.title || item.name,
|
|
2778
|
+
description: item.description || '',
|
|
2779
|
+
parentId: item.parentId,
|
|
2780
|
+
childrenCount: item.childrenCount || 0,
|
|
2781
|
+
}));
|
|
2782
|
+
},
|
|
2783
|
+
};
|
|
2784
|
+
const entity = await this.entityResolver.resolve(RootConfig.module.name, RootConfig.entities.questionBankItem.name);
|
|
2785
|
+
if (!entity) {
|
|
2786
|
+
throw new Error('Entity not found: ' + RootConfig.entities.questionBankItem.name);
|
|
2787
|
+
}
|
|
2788
|
+
const columns = entity.columns
|
|
2789
|
+
?.filter((column) => entity.properties.some((property) => property.name === column.name))
|
|
2790
|
+
.map((column) => {
|
|
2791
|
+
const property = entity.properties.find((prop) => prop.name === column.name);
|
|
2792
|
+
return {
|
|
2793
|
+
name: column.name,
|
|
2794
|
+
title: property?.title ?? '',
|
|
2795
|
+
visible: column.options?.visible !== false,
|
|
2796
|
+
widget: {
|
|
2797
|
+
type: column.showAs?.type ?? property?.schema?.interface?.type ?? 'text-editor',
|
|
2798
|
+
options: column.showAs?.options ?? property?.schema?.interface?.options ?? {},
|
|
2799
|
+
},
|
|
2800
|
+
};
|
|
2801
|
+
}) || [];
|
|
2802
|
+
// Translate titles
|
|
2803
|
+
const selectQuestionsTitle = (await this.translationService.translateAsync('@assessment-management:questionnaires.components.questionnaire-builder.select-questions')) || 'Select Questions from Question Bank';
|
|
2804
|
+
const categoriesTitle = (await this.translationService.translateAsync('@assessment-management:questionnaires.components.questionnaire-builder.categories')) || 'Categories';
|
|
2805
|
+
const titleLabel = (await this.translationService.translateAsync('@general:terms.common.title')) || 'Title';
|
|
2806
|
+
const noteLabel = (await this.translationService.translateAsync('@assessment-management:question-bank.entities.question-bank-item.fields.note.title')) || 'Note';
|
|
2807
|
+
// Open data selector with category filter
|
|
2808
|
+
const result = await this.dataSelectorService.openWithCategoryFilter({
|
|
2809
|
+
title: selectQuestionsTitle,
|
|
2810
|
+
dataSource: dataSource,
|
|
2811
|
+
columns: columns,
|
|
2812
|
+
selectionMode: 'multiple',
|
|
2813
|
+
searchFields: [
|
|
2814
|
+
{ name: 'title', title: titleLabel },
|
|
2815
|
+
{ name: 'note', title: noteLabel },
|
|
2816
|
+
],
|
|
2817
|
+
allowCreate: 'full',
|
|
2818
|
+
onCreate: (mode) => this.createQuestionBankItem(entity, mode),
|
|
2819
|
+
}, {
|
|
2820
|
+
title: categoriesTitle,
|
|
2821
|
+
dataSource: categoryTreeDataSource,
|
|
2822
|
+
filterField: 'categoryIds',
|
|
2823
|
+
filterOperator: 'contains',
|
|
2824
|
+
width: '350px',
|
|
2825
|
+
});
|
|
2826
|
+
if (result?.items && result.items.length > 0) {
|
|
2827
|
+
const questionPromises = result.items.map((item) => this.questionBankData()
|
|
2828
|
+
.byKey(item.id)
|
|
2829
|
+
.catch(() => null));
|
|
2830
|
+
const questions = await Promise.all(questionPromises);
|
|
2831
|
+
const used = collectQuestionnaireItemNames(allSections);
|
|
2832
|
+
const baseOrder = section.items.length;
|
|
2833
|
+
const newItems = result.items.map((item, index) => {
|
|
2834
|
+
const fullQuestion = questions[index];
|
|
2835
|
+
const qName = allocateNextQuestionItemName(used);
|
|
2836
|
+
used.add(qName);
|
|
2837
|
+
return {
|
|
2838
|
+
name: qName,
|
|
2839
|
+
questionBankItemId: item.id,
|
|
2840
|
+
order: baseOrder + index,
|
|
2841
|
+
isRequired: false,
|
|
2842
|
+
isVisible: undefined,
|
|
2843
|
+
isNewlyAdded: true,
|
|
2844
|
+
question: fullQuestion
|
|
2845
|
+
? {
|
|
2846
|
+
id: fullQuestion.id,
|
|
2847
|
+
title: fullQuestion.title,
|
|
2848
|
+
question: fullQuestion.question,
|
|
2849
|
+
note: fullQuestion.note,
|
|
2850
|
+
difficulty: fullQuestion.difficulty,
|
|
2851
|
+
}
|
|
2852
|
+
: {
|
|
2853
|
+
id: item.id,
|
|
2854
|
+
title: item.title || 'Question',
|
|
2855
|
+
question: item.question,
|
|
2856
|
+
note: item.note,
|
|
2857
|
+
difficulty: item.difficulty,
|
|
2858
|
+
},
|
|
2859
|
+
};
|
|
2860
|
+
});
|
|
2861
|
+
return newItems;
|
|
2862
|
+
}
|
|
2863
|
+
return null;
|
|
2864
|
+
}
|
|
2865
|
+
catch (error) {
|
|
2866
|
+
console.error('Error loading questions:', error);
|
|
2867
|
+
return null;
|
|
2868
|
+
}
|
|
2869
|
+
}
|
|
2870
|
+
/**
|
|
2871
|
+
* Create a new question bank item via Entity:Create and return it for selection in the data selector.
|
|
2872
|
+
*/
|
|
2873
|
+
async createQuestionBankItem(entity, _mode) {
|
|
2874
|
+
const result = await this.commandService.execute('Entity:Create', {
|
|
2875
|
+
__context__: {
|
|
2876
|
+
entity: `${entity.module}.${entity.name}`,
|
|
2877
|
+
entityInfo: {
|
|
2878
|
+
name: entity.name,
|
|
2879
|
+
module: entity.module,
|
|
2880
|
+
title: entity.title,
|
|
2881
|
+
parentKey: entity.parentKey,
|
|
2882
|
+
},
|
|
2883
|
+
data: {},
|
|
2884
|
+
options: {},
|
|
2885
|
+
},
|
|
2886
|
+
});
|
|
2887
|
+
if (result?.success && result?.data) {
|
|
2888
|
+
const item = Array.isArray(result.data) ? result.data[0] : result.data;
|
|
2889
|
+
return item;
|
|
2890
|
+
}
|
|
2891
|
+
return null;
|
|
2892
|
+
}
|
|
2893
|
+
/**
|
|
2894
|
+
* Maps nested `hint` from the question property viewer to persisted questionnaire item `hint` partial (diff from bank).
|
|
2895
|
+
*/
|
|
2896
|
+
persistQuestionHintFromForm(bank, hint) {
|
|
2897
|
+
if (!hint) {
|
|
2898
|
+
return undefined;
|
|
2899
|
+
}
|
|
2900
|
+
const modeRaw = hint.mode == null ? undefined : typeof hint.mode === 'string' ? hint.mode : hint.mode.id;
|
|
2901
|
+
const mode = normalizeQuestionHintMode(modeRaw) ?? 'off';
|
|
2902
|
+
const c = hint.content;
|
|
2903
|
+
let content;
|
|
2904
|
+
if (c == null) {
|
|
2905
|
+
content = undefined;
|
|
2906
|
+
}
|
|
2907
|
+
else if (typeof c === 'string') {
|
|
2908
|
+
const t = c.trim();
|
|
2909
|
+
content = t || undefined;
|
|
2910
|
+
}
|
|
2911
|
+
else if (typeof c === 'object') {
|
|
2912
|
+
content = c;
|
|
2913
|
+
}
|
|
2914
|
+
const edited = normalizeQuestionHintConfig({ mode, content });
|
|
2915
|
+
return diffQuestionHintOverride(bank, edited);
|
|
2916
|
+
}
|
|
2917
|
+
/**
|
|
2918
|
+
* Persists questionnaire item `comment` override: only fields that differ from the question bank default.
|
|
2919
|
+
*/
|
|
2920
|
+
persistQuestionCommentFromForm(bank, form) {
|
|
2921
|
+
if (!form) {
|
|
2922
|
+
return undefined;
|
|
2923
|
+
}
|
|
2924
|
+
const edited = normalizeQuestionCommentConfig(form);
|
|
2925
|
+
return diffQuestionCommentOverride(bank, edited);
|
|
2926
|
+
}
|
|
2927
|
+
/**
|
|
2928
|
+
* Normalize tag-editor output to trimmed unique strings (supports string[] or { title }[] from tag service).
|
|
2929
|
+
*/
|
|
2930
|
+
normalizeTagsFromForm(raw) {
|
|
2931
|
+
if (raw == null || !Array.isArray(raw))
|
|
2932
|
+
return undefined;
|
|
2933
|
+
const seen = new Set();
|
|
2934
|
+
const out = [];
|
|
2935
|
+
for (const entry of raw) {
|
|
2936
|
+
let t = '';
|
|
2937
|
+
if (typeof entry === 'string')
|
|
2938
|
+
t = entry.trim();
|
|
2939
|
+
else if (entry && typeof entry === 'object' && 'title' in entry) {
|
|
2940
|
+
t = String(entry.title).trim();
|
|
2941
|
+
}
|
|
2942
|
+
if (!t)
|
|
2943
|
+
continue;
|
|
2944
|
+
const key = t.toLowerCase();
|
|
2945
|
+
if (seen.has(key))
|
|
2946
|
+
continue;
|
|
2947
|
+
seen.add(key);
|
|
2948
|
+
out.push(t);
|
|
2949
|
+
}
|
|
2950
|
+
return out.length ? out : undefined;
|
|
2951
|
+
}
|
|
2952
|
+
/** Allowed characters for questionnaire item technical name (UUID-safe). */
|
|
2953
|
+
isValidQuestionnaireItemName(name) {
|
|
2954
|
+
return name.length >= 1 && name.length <= 128 && /^[a-zA-Z0-9_-]+$/.test(name);
|
|
2955
|
+
}
|
|
2956
|
+
/**
|
|
2957
|
+
* Plain heading for builder cards: prefer rich `question`, else admin list `title`.
|
|
2958
|
+
*/
|
|
2959
|
+
itemQuestionHeading(item) {
|
|
2960
|
+
const q = item.question;
|
|
2961
|
+
if (!q) {
|
|
2962
|
+
return 'Question';
|
|
2963
|
+
}
|
|
2964
|
+
const locale = this.translationService.getActiveLang?.() ?? 'en-US';
|
|
2965
|
+
const raw = q.question;
|
|
2966
|
+
if (raw != null && raw !== '') {
|
|
2967
|
+
const html = typeof raw === 'string' ? raw : resolveMultiLanguageString(raw, locale);
|
|
2968
|
+
const plain = stripHtmlToPlain(html);
|
|
2969
|
+
if (plain.trim()) {
|
|
2970
|
+
return plain;
|
|
2971
|
+
}
|
|
2972
|
+
}
|
|
2973
|
+
const titleResolved = resolveMultiLanguageString(q.title, locale);
|
|
2974
|
+
return titleResolved.trim() || 'Question';
|
|
2975
|
+
}
|
|
2976
|
+
/** Plain preview line for optional note under the heading. */
|
|
2977
|
+
itemQuestionNotePreview(item) {
|
|
2978
|
+
const raw = item.question?.note;
|
|
2979
|
+
if (raw == null || raw === '') {
|
|
2980
|
+
return '';
|
|
2981
|
+
}
|
|
2982
|
+
const locale = this.translationService.getActiveLang?.() ?? 'en-US';
|
|
2983
|
+
const html = typeof raw === 'string' ? raw : resolveMultiLanguageString(raw, locale);
|
|
2984
|
+
return stripHtmlToPlain(html);
|
|
2985
|
+
}
|
|
2986
|
+
/**
|
|
2987
|
+
* Resolve icon based on widget type, with safe fallback.
|
|
2988
|
+
*/
|
|
2989
|
+
getQuestionWidgetIcon(item) {
|
|
2990
|
+
const fallbackIcon = 'fa-light fa-question-circle';
|
|
2991
|
+
const widgetType = item.interfaceOverride?.type ?? item.question?.interface?.type;
|
|
2992
|
+
if (!widgetType) {
|
|
2993
|
+
return fallbackIcon;
|
|
2994
|
+
}
|
|
2995
|
+
try {
|
|
2996
|
+
return this.widgetRegistry.resolve(widgetType).icon ?? fallbackIcon;
|
|
2997
|
+
}
|
|
2998
|
+
catch {
|
|
2999
|
+
return fallbackIcon;
|
|
3000
|
+
}
|
|
3001
|
+
}
|
|
3002
|
+
//#endregion
|
|
3003
|
+
//#region ---- Preview ----
|
|
3004
|
+
/**
|
|
3005
|
+
* Open preview dialog with questionnaire viewer
|
|
3006
|
+
*/
|
|
3007
|
+
async handlePreview() {
|
|
3008
|
+
if (this.isPreviewDisabled()) {
|
|
3009
|
+
return;
|
|
3010
|
+
}
|
|
3011
|
+
try {
|
|
3012
|
+
const currentValue = convertStateToValue(this.builderState(), this.value() || undefined);
|
|
3013
|
+
// Always use the current displaySettings from the computed property to ensure preview uses latest settings
|
|
3014
|
+
currentValue.displaySettings = this.displaySettings();
|
|
3015
|
+
const previewTitle = (await this.translationService.translateAsync('@assessment-management:questionnaires.components.questionnaire-builder.actions.preview.title')) || 'Preview';
|
|
3016
|
+
const result = await this.questionnaireViewerService.open({
|
|
3017
|
+
title: previewTitle,
|
|
3018
|
+
structure: currentValue,
|
|
3019
|
+
prePostConfig: this.prePostConfig() ?? undefined,
|
|
3020
|
+
questionnaireId: this.questionnaireEntityId(),
|
|
3021
|
+
});
|
|
3022
|
+
// Handle result if needed (answers, submitted status)
|
|
3023
|
+
if (result) {
|
|
3024
|
+
console.log('Questionnaire preview result:', result);
|
|
3025
|
+
}
|
|
3026
|
+
}
|
|
3027
|
+
catch (error) {
|
|
3028
|
+
console.error('Error opening preview:', error);
|
|
3029
|
+
}
|
|
3030
|
+
}
|
|
3031
|
+
/**
|
|
3032
|
+
* Toggle fullscreen mode using the directive
|
|
3033
|
+
*/
|
|
3034
|
+
async handleFullscreen() {
|
|
3035
|
+
const fullscreen = this.fullscreenDirective();
|
|
3036
|
+
if (fullscreen) {
|
|
3037
|
+
await fullscreen.toggle();
|
|
3038
|
+
}
|
|
3039
|
+
}
|
|
3040
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMQuestionnaireQuestionsBuilderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
3041
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: AXMQuestionnaireQuestionsBuilderComponent, isStandalone: true, selector: "axm-questionnaire-questions-builder", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, prePostConfig: { classPropertyName: "prePostConfig", publicName: "prePostConfig", isSignal: true, isRequired: false, transformFunction: null }, showHeader: { classPropertyName: "showHeader", publicName: "showHeader", isSignal: true, isRequired: false, transformFunction: null }, displaySettingsInput: { classPropertyName: "displaySettingsInput", publicName: "displaySettingsInput", isSignal: true, isRequired: false, transformFunction: null }, questionnaireEntityId: { classPropertyName: "questionnaireEntityId", publicName: "questionnaireEntityId", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { valueChange: "valueChange" }, viewQueries: [{ propertyName: "fullscreenDirective", first: true, predicate: ["fullscreen"], descendants: true, isSignal: true }, { propertyName: "standardRef", first: true, predicate: AXPStandardSectionItemsBuilderComponent, descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"axm-questionnaire-questions-builder\" axFullscreen #fullscreen=\"axFullscreen\">\n @if (showHeader()) {\n <div class=\"__header\">\n <div class=\"__header-left\"></div>\n <div class=\"__header-right\">\n @if (!readonly()) {\n <ax-button class=\"ax-sm\" [text]=\"\n ('@assessment-management:questionnaires.components.questionnaire-builder.actions.add-section.title'\n | translate\n | async) || 'Add Section'\n \" [color]=\"'primary'\" (onClick)=\"addSection()\">\n <ax-prefix>\n <ax-icon icon=\"fa-light fa-layer-group\"></ax-icon>\n </ax-prefix>\n </ax-button>\n <ax-button class=\"ax-sm\" [title]=\"\n ('@assessment-management:questionnaires.components.questionnaire-builder.actions.preview.title'\n | translate\n | async) || 'Preview'\n \" [disabled]=\"isPreviewDisabled()\" (onClick)=\"handlePreview()\">\n <ax-icon icon=\"fa-light fa-eye\"></ax-icon>\n </ax-button>\n }\n <ax-button class=\"ax-sm\" [title]=\"\n ('@assessment-management:questionnaires.components.questionnaire-builder.actions.fullscreen.title'\n | translate\n | async) || 'Full Screen'\n \" (onClick)=\"handleFullscreen()\">\n <ax-icon icon=\"fa-light fa-expand\"></ax-icon>\n </ax-button>\n </div>\n </div>\n }\n\n <axp-standard-section-items-builder #standardRef class=\"ax-block ax-min-h-[200px]\" [value]=\"builderValue()\"\n [config]=\"standardConfig()\" [readonly]=\"readonly()\" (valueChange)=\"onBuilderValueChange($event)\" />\n</div>", styles: [".axm-questionnaire-questions-builder{display:flex;height:100%;width:100%;flex-direction:column}.axm-questionnaire-questions-builder .__header{display:flex;align-items:center;justify-content:space-between;gap:.75rem;border-bottom-width:1px;padding:.75rem}.axm-questionnaire-questions-builder .__header .__header-left,.axm-questionnaire-questions-builder .__header .__header-right{display:flex;gap:.5rem}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i1.AXButtonComponent, selector: "ax-button", inputs: ["disabled", "size", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i2.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i2.AXDecoratorGenericComponent, selector: "ax-footer, ax-header, ax-content, ax-divider, ax-form-hint, ax-prefix, ax-suffix, ax-text, ax-title, ax-subtitle, ax-placeholder, ax-overlay" }, { kind: "ngmodule", type: AXDropdownModule }, { kind: "ngmodule", type: AXFormModule }, { kind: "ngmodule", type: AXSwitchModule }, { kind: "ngmodule", type: AXLabelModule }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "component", type: AXPStandardSectionItemsBuilderComponent, selector: "axp-standard-section-items-builder", inputs: ["value", "config", "readonly"], outputs: ["valueChange"] }, { kind: "directive", type: AXFullScreenDirective, selector: "[axFullscreen]", outputs: ["fullscreenChange"], exportAs: ["axFullscreen"] }, { kind: "pipe", type: i3.AsyncPipe, name: "async" }, { kind: "pipe", type: i4.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
3042
|
+
}
|
|
3043
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMQuestionnaireQuestionsBuilderComponent, decorators: [{
|
|
3044
|
+
type: Component,
|
|
3045
|
+
args: [{ selector: 'axm-questionnaire-questions-builder', changeDetection: ChangeDetectionStrategy.OnPush, imports: [
|
|
3046
|
+
CommonModule,
|
|
3047
|
+
FormsModule,
|
|
3048
|
+
AXButtonModule,
|
|
3049
|
+
AXDecoratorModule,
|
|
3050
|
+
AXDropdownModule,
|
|
3051
|
+
AXFormModule,
|
|
3052
|
+
AXSwitchModule,
|
|
3053
|
+
AXLabelModule,
|
|
3054
|
+
AXTranslationModule,
|
|
3055
|
+
AXPStandardSectionItemsBuilderComponent,
|
|
3056
|
+
AXFullScreenDirective,
|
|
3057
|
+
], template: "<div class=\"axm-questionnaire-questions-builder\" axFullscreen #fullscreen=\"axFullscreen\">\n @if (showHeader()) {\n <div class=\"__header\">\n <div class=\"__header-left\"></div>\n <div class=\"__header-right\">\n @if (!readonly()) {\n <ax-button class=\"ax-sm\" [text]=\"\n ('@assessment-management:questionnaires.components.questionnaire-builder.actions.add-section.title'\n | translate\n | async) || 'Add Section'\n \" [color]=\"'primary'\" (onClick)=\"addSection()\">\n <ax-prefix>\n <ax-icon icon=\"fa-light fa-layer-group\"></ax-icon>\n </ax-prefix>\n </ax-button>\n <ax-button class=\"ax-sm\" [title]=\"\n ('@assessment-management:questionnaires.components.questionnaire-builder.actions.preview.title'\n | translate\n | async) || 'Preview'\n \" [disabled]=\"isPreviewDisabled()\" (onClick)=\"handlePreview()\">\n <ax-icon icon=\"fa-light fa-eye\"></ax-icon>\n </ax-button>\n }\n <ax-button class=\"ax-sm\" [title]=\"\n ('@assessment-management:questionnaires.components.questionnaire-builder.actions.fullscreen.title'\n | translate\n | async) || 'Full Screen'\n \" (onClick)=\"handleFullscreen()\">\n <ax-icon icon=\"fa-light fa-expand\"></ax-icon>\n </ax-button>\n </div>\n </div>\n }\n\n <axp-standard-section-items-builder #standardRef class=\"ax-block ax-min-h-[200px]\" [value]=\"builderValue()\"\n [config]=\"standardConfig()\" [readonly]=\"readonly()\" (valueChange)=\"onBuilderValueChange($event)\" />\n</div>", styles: [".axm-questionnaire-questions-builder{display:flex;height:100%;width:100%;flex-direction:column}.axm-questionnaire-questions-builder .__header{display:flex;align-items:center;justify-content:space-between;gap:.75rem;border-bottom-width:1px;padding:.75rem}.axm-questionnaire-questions-builder .__header .__header-left,.axm-questionnaire-questions-builder .__header .__header-right{display:flex;gap:.5rem}\n"] }]
|
|
3058
|
+
}], ctorParameters: () => [], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], prePostConfig: [{ type: i0.Input, args: [{ isSignal: true, alias: "prePostConfig", required: false }] }], showHeader: [{ type: i0.Input, args: [{ isSignal: true, alias: "showHeader", required: false }] }], displaySettingsInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "displaySettingsInput", required: false }] }], questionnaireEntityId: [{ type: i0.Input, args: [{ isSignal: true, alias: "questionnaireEntityId", required: false }] }], valueChange: [{ type: i0.Output, args: ["valueChange"] }], fullscreenDirective: [{ type: i0.ViewChild, args: ['fullscreen', { isSignal: true }] }], standardRef: [{ type: i0.ViewChild, args: [i0.forwardRef(() => AXPStandardSectionItemsBuilderComponent), { isSignal: true }] }] } });
|
|
3059
|
+
|
|
3060
|
+
/** Component key for the questionnaire Questions page tab. Register via AXP_PAGE_COMPONENT_PROVIDER. */
|
|
3061
|
+
const QUESTIONNAIRE_QUESTIONS_PAGE_COMPONENT_KEY = 'questionnaire-questions-page';
|
|
3062
|
+
|
|
3063
|
+
const QUESTIONNAIRE_QUESTIONS_SAVE_COMMAND = 'Questionnaire:Questions:Save';
|
|
3064
|
+
/**
|
|
3065
|
+
* Command to save the questionnaire questions field.
|
|
3066
|
+
* By default uses entity update (patch) with { questions }.
|
|
3067
|
+
* Can be overridden for custom API logic.
|
|
3068
|
+
*/
|
|
3069
|
+
class AXMSaveQuestionnaireQuestionsCommand {
|
|
3070
|
+
constructor() {
|
|
3071
|
+
this.entityService = inject(AXPEntityService);
|
|
3072
|
+
this.translationService = inject(AXTranslationService);
|
|
3073
|
+
}
|
|
3074
|
+
async execute(input) {
|
|
3075
|
+
const { id, questions } = input;
|
|
3076
|
+
if (!id) {
|
|
3077
|
+
return {
|
|
3078
|
+
success: false,
|
|
3079
|
+
message: {
|
|
3080
|
+
text: await this.translationService.translateAsync('@general:messages.entity.invalid-data'),
|
|
3081
|
+
},
|
|
3082
|
+
};
|
|
3083
|
+
}
|
|
3084
|
+
try {
|
|
3085
|
+
const entityRef = `${RootConfig.module.name}.${RootConfig.entities.questionnaire.name}`;
|
|
3086
|
+
const dataAccessor = this.entityService.withEntity(entityRef).data();
|
|
3087
|
+
await dataAccessor.update(id, { questions });
|
|
3088
|
+
return {
|
|
3089
|
+
success: true,
|
|
3090
|
+
data: { id, questions },
|
|
3091
|
+
message: {
|
|
3092
|
+
text: await this.translationService.translateAsync('@general:messages.generic.success.description'),
|
|
3093
|
+
},
|
|
3094
|
+
};
|
|
3095
|
+
}
|
|
3096
|
+
catch (error) {
|
|
3097
|
+
const message = error instanceof Error
|
|
3098
|
+
? error.message
|
|
3099
|
+
: await this.translationService.translateAsync('@general:messages.generic.error.description');
|
|
3100
|
+
return {
|
|
3101
|
+
success: false,
|
|
3102
|
+
message: { text: message },
|
|
3103
|
+
};
|
|
3104
|
+
}
|
|
3105
|
+
}
|
|
3106
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMSaveQuestionnaireQuestionsCommand, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
3107
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMSaveQuestionnaireQuestionsCommand, providedIn: 'root' }); }
|
|
3108
|
+
}
|
|
3109
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMSaveQuestionnaireQuestionsCommand, decorators: [{
|
|
3110
|
+
type: Injectable,
|
|
3111
|
+
args: [{
|
|
3112
|
+
providedIn: 'root',
|
|
3113
|
+
}]
|
|
3114
|
+
}] });
|
|
3115
|
+
|
|
3116
|
+
var saveQuestionnaireQuestions_command = /*#__PURE__*/Object.freeze({
|
|
3117
|
+
__proto__: null,
|
|
3118
|
+
AXMSaveQuestionnaireQuestionsCommand: AXMSaveQuestionnaireQuestionsCommand,
|
|
3119
|
+
QUESTIONNAIRE_QUESTIONS_SAVE_COMMAND: QUESTIONNAIRE_QUESTIONS_SAVE_COMMAND
|
|
3120
|
+
});
|
|
3121
|
+
|
|
3122
|
+
/** Local command handled in execute(); reverts questions to rootContext (no AXPCommand). */
|
|
3123
|
+
const QUESTIONNAIRE_QUESTIONS_DISCARD_COMMAND = 'Questionnaire:Questions:Discard';
|
|
3124
|
+
const QUESTIONNAIRE_QUESTIONS_ADD_SECTION_COMMAND = 'Questionnaire:Questions:AddSection';
|
|
3125
|
+
const QUESTIONNAIRE_QUESTIONS_PREVIEW_COMMAND = 'Questionnaire:Questions:Preview';
|
|
3126
|
+
//#region ---- Questionnaire Questions Page Component ----
|
|
3127
|
+
/**
|
|
3128
|
+
* Page component that renders the questions property using axm-questionnaire-questions-builder.
|
|
3129
|
+
* Extends AXPPageLayoutBaseComponent to provide a Save button that persists questions via Questionnaire:Questions:Save.
|
|
3130
|
+
* Receives rootContext (entity data).
|
|
3131
|
+
*/
|
|
3132
|
+
class AXMQuestionnaireQuestionsPageComponent extends AXPPageLayoutBaseComponent {
|
|
3133
|
+
//#endregion
|
|
3134
|
+
//#region ---- Lifecycle ----
|
|
3135
|
+
constructor() {
|
|
3136
|
+
super();
|
|
3137
|
+
//#region ---- Inputs ----
|
|
3138
|
+
this.rootContext = input(...(ngDevMode ? [undefined, { debugName: "rootContext" }] : /* istanbul ignore next */ []));
|
|
3139
|
+
/** Optional page config (e.g. field, layout) set by the page-component-renderer. */
|
|
3140
|
+
this.pageConfig = input(...(ngDevMode ? [undefined, { debugName: "pageConfig" }] : /* istanbul ignore next */ []));
|
|
3141
|
+
//#endregion
|
|
3142
|
+
//#region ---- Services & Dependencies ----
|
|
3143
|
+
this.commandService = inject(AXPCommandService);
|
|
3144
|
+
this.eventService = inject(AXPBroadcastEventService);
|
|
3145
|
+
this.hostPageLayout = inject(AXPPageLayoutBase, { optional: true, skipSelf: true });
|
|
3146
|
+
//#endregion
|
|
3147
|
+
//#region ---- View References ----
|
|
3148
|
+
this.builderRef = viewChild('builderRef', ...(ngDevMode ? [{ debugName: "builderRef" }] : /* istanbul ignore next */ []));
|
|
3149
|
+
//#endregion
|
|
3150
|
+
//#region ---- State Signals ----
|
|
3151
|
+
/** Latest context (includes edited questions). Used for Save when rootContext is not updated by the parent. */
|
|
3152
|
+
this.localContext = signal(null, ...(ngDevMode ? [{ debugName: "localContext" }] : /* istanbul ignore next */ []));
|
|
3153
|
+
/** When true, the next valueChange from the builder is ignored (avoids undoing discard due to stale emit). */
|
|
3154
|
+
this.ignoreNextValueChange = signal(false, ...(ngDevMode ? [{ debugName: "ignoreNextValueChange" }] : /* istanbul ignore next */ []));
|
|
3155
|
+
/** Stable pre/post config so we don't pass a new object every CD (avoids infinite loop). */
|
|
3156
|
+
this.prePostConfigStable = signal(null, ...(ngDevMode ? [{ debugName: "prePostConfigStable" }] : /* istanbul ignore next */ []));
|
|
3157
|
+
/** Baseline snapshot of questions for dirty checks. */
|
|
3158
|
+
this.baselineQuestions = signal(null, ...(ngDevMode ? [{ debugName: "baselineQuestions" }] : /* istanbul ignore next */ []));
|
|
3159
|
+
/**
|
|
3160
|
+
* When true, the next builder emission should realign the baseline to the builder's canonical shape.
|
|
3161
|
+
* Root/API `questions` often differs from the normalized object emitted by the builder (defaults, ordering, derived fields), which would otherwise keep `isDirty` true on load and after discard/save.
|
|
3162
|
+
*/
|
|
3163
|
+
this.questionsBaselinePendingReconcile = signal(false, ...(ngDevMode ? [{ debugName: "questionsBaselinePendingReconcile" }] : /* istanbul ignore next */ []));
|
|
3164
|
+
this.isDirty = signal(false, ...(ngDevMode ? [{ debugName: "isDirty" }] : /* istanbul ignore next */ []));
|
|
3165
|
+
//#endregion
|
|
3166
|
+
//#region ---- Computed State ----
|
|
3167
|
+
/** Current context: prefer local updates so edits are preserved. */
|
|
3168
|
+
this.context = computed(() => {
|
|
3169
|
+
const local = this.localContext();
|
|
3170
|
+
if (local != null)
|
|
3171
|
+
return local;
|
|
3172
|
+
return this.rootContext() ?? {};
|
|
3173
|
+
}, ...(ngDevMode ? [{ debugName: "context" }] : /* istanbul ignore next */ []));
|
|
3174
|
+
/** Questions value passed to the builder (from context). */
|
|
3175
|
+
this.questionsValue = computed(() => {
|
|
3176
|
+
const ctx = this.context();
|
|
3177
|
+
const q = ctx['questions'];
|
|
3178
|
+
return (q != null && typeof q === 'object' ? q : null);
|
|
3179
|
+
}, ...(ngDevMode ? [{ debugName: "questionsValue" }] : /* istanbul ignore next */ []));
|
|
3180
|
+
/** Pre/post config for preview; stable reference to avoid infinite change detection. */
|
|
3181
|
+
this.prePostConfig = computed(() => this.prePostConfigStable(), ...(ngDevMode ? [{ debugName: "prePostConfig" }] : /* istanbul ignore next */ []));
|
|
3182
|
+
/** Display settings from entity (for builder preview). */
|
|
3183
|
+
this.entityDisplaySettings = computed(() => toDisplaySettings((this.rootContext() ?? undefined)) ?? null, ...(ngDevMode ? [{ debugName: "entityDisplaySettings" }] : /* istanbul ignore next */ []));
|
|
3184
|
+
/** Questionnaire entity id for preview outcome evaluation. */
|
|
3185
|
+
this.questionnaireEntityId = computed(() => {
|
|
3186
|
+
const id = this.rootContext()?.['id'];
|
|
3187
|
+
return typeof id === 'string' && id.length > 0 ? id : undefined;
|
|
3188
|
+
}, ...(ngDevMode ? [{ debugName: "questionnaireEntityId" }] : /* istanbul ignore next */ []));
|
|
3189
|
+
let previousRootId = undefined;
|
|
3190
|
+
effect(() => {
|
|
3191
|
+
const ctx = this.rootContext();
|
|
3192
|
+
const currentId = ctx != null && typeof ctx === 'object' ? ctx['id'] : undefined;
|
|
3193
|
+
if (currentId !== previousRootId) {
|
|
3194
|
+
previousRootId = currentId;
|
|
3195
|
+
this.localContext.set(null);
|
|
3196
|
+
const rootQuestions = ctx?.['questions'];
|
|
3197
|
+
this.baselineQuestions.set(this.cloneQuestions(rootQuestions));
|
|
3198
|
+
this.isDirty.set(false);
|
|
3199
|
+
this.questionsBaselinePendingReconcile.set(true);
|
|
3200
|
+
}
|
|
3201
|
+
});
|
|
3202
|
+
let lastPrePostKey = '';
|
|
3203
|
+
effect(() => {
|
|
3204
|
+
const ctx = this.rootContext();
|
|
3205
|
+
const next = toPrePostConfig(ctx ?? undefined);
|
|
3206
|
+
const key = next ? JSON.stringify(next) : '';
|
|
3207
|
+
if (key !== lastPrePostKey) {
|
|
3208
|
+
lastPrePostKey = key;
|
|
3209
|
+
this.prePostConfigStable.set(next);
|
|
3210
|
+
}
|
|
3211
|
+
});
|
|
3212
|
+
}
|
|
3213
|
+
//#endregion
|
|
3214
|
+
//#region ---- Page Actions ----
|
|
3215
|
+
async getPrimaryMenuItems() {
|
|
3216
|
+
const addSectionTitle = (await this.translateService.translateAsync('@assessment-management:questionnaires.components.questionnaire-builder.actions.add-section.title')) || 'Add Section';
|
|
3217
|
+
const previewTitle = (await this.translateService.translateAsync('@assessment-management:questionnaires.components.questionnaire-builder.actions.preview.title')) || 'Preview';
|
|
3218
|
+
const discardTitle = (await this.translateService.translateAsync('@general:actions.discard.title')) || 'Discard';
|
|
3219
|
+
const saveTitle = (await this.translateService.translateAsync('@general:actions.save.title')) || 'Save';
|
|
3220
|
+
const addSectionAction = {
|
|
3221
|
+
title: addSectionTitle,
|
|
3222
|
+
icon: 'fa-light fa-layer-group',
|
|
3223
|
+
zone: 'header',
|
|
3224
|
+
priority: 'primary',
|
|
3225
|
+
color: 'primary',
|
|
3226
|
+
command: {
|
|
3227
|
+
name: QUESTIONNAIRE_QUESTIONS_ADD_SECTION_COMMAND,
|
|
3228
|
+
options: {},
|
|
3229
|
+
},
|
|
3230
|
+
};
|
|
3231
|
+
const previewAction = {
|
|
3232
|
+
title: previewTitle,
|
|
3233
|
+
icon: 'fa-light fa-eye',
|
|
3234
|
+
zone: 'header',
|
|
3235
|
+
priority: 'primary',
|
|
3236
|
+
color: 'default',
|
|
3237
|
+
command: {
|
|
3238
|
+
name: QUESTIONNAIRE_QUESTIONS_PREVIEW_COMMAND,
|
|
3239
|
+
options: {},
|
|
3240
|
+
},
|
|
3241
|
+
};
|
|
3242
|
+
const discardAction = {
|
|
3243
|
+
title: discardTitle,
|
|
3244
|
+
icon: 'fa-light fa-rotate-left',
|
|
3245
|
+
zone: 'footer',
|
|
3246
|
+
priority: 'secondary',
|
|
3247
|
+
color: 'default',
|
|
3248
|
+
visible: this.isDirty(),
|
|
3249
|
+
command: {
|
|
3250
|
+
name: QUESTIONNAIRE_QUESTIONS_DISCARD_COMMAND,
|
|
3251
|
+
options: {},
|
|
3252
|
+
},
|
|
3253
|
+
};
|
|
3254
|
+
const saveAction = {
|
|
3255
|
+
title: saveTitle,
|
|
3256
|
+
icon: 'fa-light fa-floppy-disk',
|
|
3257
|
+
zone: 'footer',
|
|
3258
|
+
priority: 'primary',
|
|
3259
|
+
color: 'primary',
|
|
3260
|
+
visible: this.isDirty(),
|
|
3261
|
+
command: {
|
|
3262
|
+
name: QUESTIONNAIRE_QUESTIONS_SAVE_COMMAND,
|
|
3263
|
+
options: {},
|
|
3264
|
+
},
|
|
3265
|
+
};
|
|
3266
|
+
return [addSectionAction, previewAction, discardAction, saveAction];
|
|
3267
|
+
}
|
|
3268
|
+
//#endregion
|
|
3269
|
+
//#region ---- Command Handling ----
|
|
3270
|
+
execute(command) {
|
|
3271
|
+
if (command.name === QUESTIONNAIRE_QUESTIONS_DISCARD_COMMAND) {
|
|
3272
|
+
this.ignoreNextValueChange.set(true);
|
|
3273
|
+
this.localContext.set(null);
|
|
3274
|
+
this.isDirty.set(false);
|
|
3275
|
+
this.questionsBaselinePendingReconcile.set(true);
|
|
3276
|
+
this.recompute();
|
|
3277
|
+
return;
|
|
3278
|
+
}
|
|
3279
|
+
if (command.name === QUESTIONNAIRE_QUESTIONS_ADD_SECTION_COMMAND) {
|
|
3280
|
+
void this.builderRef()?.addSection();
|
|
3281
|
+
return;
|
|
3282
|
+
}
|
|
3283
|
+
if (command.name === QUESTIONNAIRE_QUESTIONS_PREVIEW_COMMAND) {
|
|
3284
|
+
this.builderRef()?.handlePreview();
|
|
3285
|
+
return;
|
|
3286
|
+
}
|
|
3287
|
+
if (command.name !== QUESTIONNAIRE_QUESTIONS_SAVE_COMMAND) {
|
|
3288
|
+
return;
|
|
3289
|
+
}
|
|
3290
|
+
// Return result for delegateExecute; cast needed to satisfy base signature
|
|
3291
|
+
return this.handleSaveExecute();
|
|
3292
|
+
}
|
|
3293
|
+
async handleSaveExecute() {
|
|
3294
|
+
const ctx = this.localContext() ?? this.rootContext() ?? {};
|
|
3295
|
+
const id = typeof ctx['id'] === 'string' ? ctx['id'] : undefined;
|
|
3296
|
+
const questions = ctx['questions'];
|
|
3297
|
+
if (!id) {
|
|
3298
|
+
return {
|
|
3299
|
+
success: false,
|
|
3300
|
+
message: {
|
|
3301
|
+
text: await this.translateService.translateAsync('@general:messages.entity.invalid-data'),
|
|
3302
|
+
},
|
|
3303
|
+
};
|
|
3304
|
+
}
|
|
3305
|
+
const input = {
|
|
3306
|
+
id,
|
|
3307
|
+
questions: questions ?? { sections: [] },
|
|
3308
|
+
};
|
|
3309
|
+
const result = await this.commandService.execute(QUESTIONNAIRE_QUESTIONS_SAVE_COMMAND, input);
|
|
3310
|
+
const execResult = (result ?? { success: false });
|
|
3311
|
+
if (execResult.success) {
|
|
3312
|
+
const savedQuestions = questions ?? { sections: [] };
|
|
3313
|
+
this.baselineQuestions.set(this.cloneQuestions(savedQuestions));
|
|
3314
|
+
this.localContext.set(null);
|
|
3315
|
+
this.isDirty.set(false);
|
|
3316
|
+
this.questionsBaselinePendingReconcile.set(true);
|
|
3317
|
+
this.recompute();
|
|
3318
|
+
this.eventService.publish(AXPEntityEventsKeys.REFRESH_LAYOUT, {
|
|
3319
|
+
name: `${RootConfig.module.name}.${RootConfig.entities.questionnaire.name}`,
|
|
3320
|
+
});
|
|
3321
|
+
// Success toast is shown by details-view when execute() returns success
|
|
3322
|
+
}
|
|
3323
|
+
return execResult;
|
|
3324
|
+
}
|
|
3325
|
+
//#endregion
|
|
3326
|
+
//#region ---- UI Handlers ----
|
|
3327
|
+
/** Updates local context when the builder emits a new questions value. Skip if unchanged to avoid CD loop. */
|
|
3328
|
+
onQuestionsChange(value) {
|
|
3329
|
+
if (this.ignoreNextValueChange()) {
|
|
3330
|
+
this.ignoreNextValueChange.set(false);
|
|
3331
|
+
return;
|
|
3332
|
+
}
|
|
3333
|
+
const current = this.questionsValue();
|
|
3334
|
+
if (this.areQuestionsEqual(current ?? undefined, value ?? undefined)) {
|
|
3335
|
+
if (this.questionsBaselinePendingReconcile()) {
|
|
3336
|
+
const aligned = current ?? value;
|
|
3337
|
+
this.baselineQuestions.set(this.cloneQuestions(aligned ?? undefined));
|
|
3338
|
+
this.questionsBaselinePendingReconcile.set(false);
|
|
3339
|
+
this.isDirty.set(false);
|
|
3340
|
+
}
|
|
3341
|
+
return;
|
|
3342
|
+
}
|
|
3343
|
+
const base = this.localContext() ?? this.rootContext() ?? {};
|
|
3344
|
+
if (this.questionsBaselinePendingReconcile() && this.localContext() == null) {
|
|
3345
|
+
this.baselineQuestions.set(this.cloneQuestions(value));
|
|
3346
|
+
this.isDirty.set(false);
|
|
3347
|
+
this.questionsBaselinePendingReconcile.set(false);
|
|
3348
|
+
this.localContext.set({ ...base, questions: value });
|
|
3349
|
+
this.recompute();
|
|
3350
|
+
return;
|
|
3351
|
+
}
|
|
3352
|
+
this.localContext.set({ ...base, questions: value });
|
|
3353
|
+
const baseline = this.baselineQuestions();
|
|
3354
|
+
const dirty = !this.areQuestionsEqual(baseline, value);
|
|
3355
|
+
this.isDirty.set(dirty);
|
|
3356
|
+
this.recompute();
|
|
3357
|
+
}
|
|
3358
|
+
//#endregion
|
|
3359
|
+
//#region ---- Utility Methods ----
|
|
3360
|
+
areQuestionsEqual(a, b) {
|
|
3361
|
+
return isEqual(a, b);
|
|
3362
|
+
}
|
|
3363
|
+
cloneQuestions(value) {
|
|
3364
|
+
if (isNil(value))
|
|
3365
|
+
return value;
|
|
3366
|
+
return cloneDeep(value);
|
|
3367
|
+
}
|
|
3368
|
+
recompute() {
|
|
3369
|
+
super.recompute();
|
|
3370
|
+
const maybeLayout = this.hostPageLayout;
|
|
3371
|
+
maybeLayout.recompute?.();
|
|
3372
|
+
}
|
|
3373
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMQuestionnaireQuestionsPageComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
3374
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "21.2.9", type: AXMQuestionnaireQuestionsPageComponent, isStandalone: true, selector: "axm-questionnaire-questions-page", inputs: { rootContext: { classPropertyName: "rootContext", publicName: "rootContext", isSignal: true, isRequired: false, transformFunction: null }, pageConfig: { classPropertyName: "pageConfig", publicName: "pageConfig", isSignal: true, isRequired: false, transformFunction: null } }, providers: [
|
|
3375
|
+
{
|
|
3376
|
+
provide: AXPPageLayoutBase,
|
|
3377
|
+
useExisting: AXMQuestionnaireQuestionsPageComponent,
|
|
3378
|
+
},
|
|
3379
|
+
], viewQueries: [{ propertyName: "builderRef", first: true, predicate: ["builderRef"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: `
|
|
3380
|
+
<axm-questionnaire-questions-builder
|
|
3381
|
+
#builderRef
|
|
3382
|
+
[value]="questionsValue()"
|
|
3383
|
+
[prePostConfig]="prePostConfig()"
|
|
3384
|
+
[displaySettingsInput]="entityDisplaySettings()"
|
|
3385
|
+
[questionnaireEntityId]="questionnaireEntityId()"
|
|
3386
|
+
[showHeader]="false"
|
|
3387
|
+
(valueChange)="onQuestionsChange($event)">
|
|
3388
|
+
</axm-questionnaire-questions-builder>
|
|
3389
|
+
`, isInline: true, dependencies: [{ kind: "component", type: AXMQuestionnaireQuestionsBuilderComponent, selector: "axm-questionnaire-questions-builder", inputs: ["value", "readonly", "prePostConfig", "showHeader", "displaySettingsInput", "questionnaireEntityId"], outputs: ["valueChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
3390
|
+
}
|
|
3391
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMQuestionnaireQuestionsPageComponent, decorators: [{
|
|
3392
|
+
type: Component,
|
|
3393
|
+
args: [{
|
|
3394
|
+
selector: 'axm-questionnaire-questions-page',
|
|
3395
|
+
standalone: true,
|
|
3396
|
+
imports: [AXMQuestionnaireQuestionsBuilderComponent],
|
|
3397
|
+
template: `
|
|
3398
|
+
<axm-questionnaire-questions-builder
|
|
3399
|
+
#builderRef
|
|
3400
|
+
[value]="questionsValue()"
|
|
3401
|
+
[prePostConfig]="prePostConfig()"
|
|
3402
|
+
[displaySettingsInput]="entityDisplaySettings()"
|
|
3403
|
+
[questionnaireEntityId]="questionnaireEntityId()"
|
|
3404
|
+
[showHeader]="false"
|
|
3405
|
+
(valueChange)="onQuestionsChange($event)">
|
|
3406
|
+
</axm-questionnaire-questions-builder>
|
|
3407
|
+
`,
|
|
3408
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
3409
|
+
providers: [
|
|
3410
|
+
{
|
|
3411
|
+
provide: AXPPageLayoutBase,
|
|
3412
|
+
useExisting: AXMQuestionnaireQuestionsPageComponent,
|
|
3413
|
+
},
|
|
3414
|
+
],
|
|
3415
|
+
}]
|
|
3416
|
+
}], ctorParameters: () => [], propDecorators: { rootContext: [{ type: i0.Input, args: [{ isSignal: true, alias: "rootContext", required: false }] }], pageConfig: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageConfig", required: false }] }], builderRef: [{ type: i0.ViewChild, args: ['builderRef', { isSignal: true }] }] } });
|
|
3417
|
+
|
|
3418
|
+
var questionnaireQuestionsPage_component = /*#__PURE__*/Object.freeze({
|
|
3419
|
+
__proto__: null,
|
|
3420
|
+
AXMQuestionnaireQuestionsPageComponent: AXMQuestionnaireQuestionsPageComponent
|
|
3421
|
+
});
|
|
3422
|
+
|
|
3423
|
+
//#region ---- Questionnaire Questions Page Component Provider ----
|
|
3424
|
+
class AXMQuestionnaireQuestionsPageComponentProvider {
|
|
3425
|
+
async components() {
|
|
3426
|
+
return [
|
|
3427
|
+
{
|
|
3428
|
+
key: QUESTIONNAIRE_QUESTIONS_PAGE_COMPONENT_KEY,
|
|
3429
|
+
loader: () => Promise.resolve().then(function () { return questionnaireQuestionsPage_component; }).then((m) => m.AXMQuestionnaireQuestionsPageComponent),
|
|
3430
|
+
},
|
|
3431
|
+
];
|
|
3432
|
+
}
|
|
3433
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMQuestionnaireQuestionsPageComponentProvider, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
3434
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMQuestionnaireQuestionsPageComponentProvider }); }
|
|
3435
|
+
}
|
|
3436
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMQuestionnaireQuestionsPageComponentProvider, decorators: [{
|
|
3437
|
+
type: Injectable
|
|
3438
|
+
}] });
|
|
3439
|
+
|
|
3440
|
+
var index$1 = /*#__PURE__*/Object.freeze({
|
|
3441
|
+
__proto__: null,
|
|
3442
|
+
AXMQuestionnaireQuestionsPageComponent: AXMQuestionnaireQuestionsPageComponent,
|
|
3443
|
+
AXMQuestionnaireQuestionsPageComponentProvider: AXMQuestionnaireQuestionsPageComponentProvider,
|
|
3444
|
+
AXMSaveQuestionnaireQuestionsCommand: AXMSaveQuestionnaireQuestionsCommand,
|
|
3445
|
+
QUESTIONNAIRE_QUESTIONS_PAGE_COMPONENT_KEY: QUESTIONNAIRE_QUESTIONS_PAGE_COMPONENT_KEY,
|
|
3446
|
+
QUESTIONNAIRE_QUESTIONS_SAVE_COMMAND: QUESTIONNAIRE_QUESTIONS_SAVE_COMMAND
|
|
3447
|
+
});
|
|
3448
|
+
|
|
3449
|
+
//#region ---- Questions builder exports ----
|
|
3450
|
+
//#endregion
|
|
3451
|
+
|
|
3452
|
+
//#region ---- Imports ----
|
|
3453
|
+
//#endregion
|
|
3454
|
+
//#region ---- Select options ----
|
|
3455
|
+
/** i18n keys for comparison operator select options. */
|
|
3456
|
+
const OUTCOME_DISPLAY_OPERATOR_LABEL_KEYS = {
|
|
3457
|
+
eq: '@assessment-management:questionnaires.components.questionnaire-outcomes-builder.fields.display-operator.options.eq',
|
|
3458
|
+
neq: '@assessment-management:questionnaires.components.questionnaire-outcomes-builder.fields.display-operator.options.neq',
|
|
3459
|
+
gt: '@assessment-management:questionnaires.components.questionnaire-outcomes-builder.fields.display-operator.options.gt',
|
|
3460
|
+
gte: '@assessment-management:questionnaires.components.questionnaire-outcomes-builder.fields.display-operator.options.gte',
|
|
3461
|
+
lt: '@assessment-management:questionnaires.components.questionnaire-outcomes-builder.fields.display-operator.options.lt',
|
|
3462
|
+
lte: '@assessment-management:questionnaires.components.questionnaire-outcomes-builder.fields.display-operator.options.lte',
|
|
3463
|
+
};
|
|
3464
|
+
/** i18n keys for emphasis select options. */
|
|
3465
|
+
const OUTCOME_DISPLAY_EMPHASIS_LABEL_KEYS = {
|
|
3466
|
+
normal: '@assessment-management:questionnaires.components.questionnaire-outcomes-builder.fields.display-emphasis.options.normal',
|
|
3467
|
+
medium: '@assessment-management:questionnaires.components.questionnaire-outcomes-builder.fields.display-emphasis.options.medium',
|
|
3468
|
+
bold: '@assessment-management:questionnaires.components.questionnaire-outcomes-builder.fields.display-emphasis.options.bold',
|
|
3469
|
+
};
|
|
3470
|
+
const OUTCOME_DISPLAY_OPERATOR_SELECT_OPTIONS = Object.keys(OUTCOME_DISPLAY_OPERATOR_LABEL_KEYS).map((id) => ({
|
|
3471
|
+
id,
|
|
3472
|
+
title: OUTCOME_DISPLAY_OPERATOR_LABEL_KEYS[id],
|
|
3473
|
+
}));
|
|
3474
|
+
const OUTCOME_DISPLAY_OPERATOR_STRING_SELECT_OPTIONS = OUTCOME_DISPLAY_OPERATOR_SELECT_OPTIONS.filter((option) => option.id === 'eq' || option.id === 'neq');
|
|
3475
|
+
const OUTCOME_DISPLAY_OPERATOR_BOOLEAN_SELECT_OPTIONS = OUTCOME_DISPLAY_OPERATOR_SELECT_OPTIONS.filter((option) => option.id === 'eq');
|
|
3476
|
+
const OUTCOME_DISPLAY_EMPHASIS_SELECT_OPTIONS = Object.keys(OUTCOME_DISPLAY_EMPHASIS_LABEL_KEYS).map((id) => ({
|
|
3477
|
+
id,
|
|
3478
|
+
title: OUTCOME_DISPLAY_EMPHASIS_LABEL_KEYS[id],
|
|
3479
|
+
}));
|
|
3480
|
+
function toOutcomeDisplayOperatorSelectValue(operator) {
|
|
3481
|
+
return { id: operator, title: OUTCOME_DISPLAY_OPERATOR_LABEL_KEYS[operator] };
|
|
3482
|
+
}
|
|
3483
|
+
function toOutcomeDisplayEmphasisSelectValue(emphasis) {
|
|
3484
|
+
return { id: emphasis, title: OUTCOME_DISPLAY_EMPHASIS_LABEL_KEYS[emphasis] };
|
|
3485
|
+
}
|
|
3486
|
+
//#endregion
|
|
3487
|
+
|
|
3488
|
+
//#region ---- Imports ----
|
|
3489
|
+
//#endregion
|
|
3490
|
+
//#region ---- Result kind labels ----
|
|
3491
|
+
/** i18n keys for select options (property viewer). */
|
|
3492
|
+
const OUTCOME_RESULT_KIND_LABEL_KEYS = {
|
|
3493
|
+
number: '@assessment-management:questionnaires.components.questionnaire-outcomes-builder.fields.result-kind.options.number',
|
|
3494
|
+
string: '@assessment-management:questionnaires.components.questionnaire-outcomes-builder.fields.result-kind.options.string',
|
|
3495
|
+
boolean: '@assessment-management:questionnaires.components.questionnaire-outcomes-builder.fields.result-kind.options.boolean',
|
|
3496
|
+
};
|
|
3497
|
+
/**
|
|
3498
|
+
* Sync labels for list badges — mirrors i18n `result-kind.options` (en-US Title Case).
|
|
3499
|
+
* Select/editor fields still use {@link OUTCOME_RESULT_KIND_LABEL_KEYS} with the translate pipe.
|
|
3500
|
+
*/
|
|
3501
|
+
const OUTCOME_RESULT_KIND_LABELS = {
|
|
3502
|
+
number: createMultiLanguageString('Number', 'عدد'),
|
|
3503
|
+
string: createMultiLanguageString('Text', 'متن'),
|
|
3504
|
+
boolean: createMultiLanguageString('Yes / No', 'بله / خیر'),
|
|
3505
|
+
};
|
|
3506
|
+
const OUTCOME_RESULT_KIND_SELECT_OPTIONS = Object.keys(OUTCOME_RESULT_KIND_LABEL_KEYS).map((id) => ({
|
|
3507
|
+
id,
|
|
3508
|
+
title: OUTCOME_RESULT_KIND_LABEL_KEYS[id],
|
|
3509
|
+
}));
|
|
3510
|
+
function resolveOutcomeResultKindLabel(kind, locale) {
|
|
3511
|
+
return resolveMultiLanguageString(OUTCOME_RESULT_KIND_LABELS[kind], locale);
|
|
3512
|
+
}
|
|
3513
|
+
function toOutcomeResultKindSelectValue(kind) {
|
|
3514
|
+
return { id: kind, title: OUTCOME_RESULT_KIND_LABEL_KEYS[kind] };
|
|
3515
|
+
}
|
|
3516
|
+
//#endregion
|
|
3517
|
+
|
|
3518
|
+
//#region ---- Imports ----
|
|
3519
|
+
//#endregion
|
|
3520
|
+
//#region ---- Groups ----
|
|
3521
|
+
const GROUP_BASIC = {
|
|
3522
|
+
name: 'basic-info',
|
|
3523
|
+
title: '@general:terms.interface.basic-info',
|
|
3524
|
+
order: 0,
|
|
3525
|
+
};
|
|
3526
|
+
const GROUP_RESULT = {
|
|
3527
|
+
name: 'result',
|
|
3528
|
+
title: '@assessment-management:questionnaires.components.questionnaire-outcomes-builder.groups.result',
|
|
3529
|
+
order: 1,
|
|
3530
|
+
};
|
|
3531
|
+
const GROUP_DISPLAY_RULES = {
|
|
3532
|
+
name: 'display-rules',
|
|
3533
|
+
title: '@assessment-management:questionnaires.components.questionnaire-outcomes-builder.groups.display-rules',
|
|
3534
|
+
order: 2,
|
|
3535
|
+
};
|
|
3536
|
+
const RESULT_KIND_OPTIONS = OUTCOME_RESULT_KIND_SELECT_OPTIONS;
|
|
3537
|
+
const DISPLAY_RULE_GRID_CELL = {
|
|
3538
|
+
alignSelf: 'center',
|
|
3539
|
+
alignItems: 'center',
|
|
3540
|
+
justifyContent: 'center',
|
|
3541
|
+
};
|
|
3542
|
+
const COMPARE_VALUE_PLACEHOLDER = '@assessment-management:questionnaires.components.questionnaire-outcomes-builder.fields.display-compare-value.placeholder';
|
|
3543
|
+
//#endregion
|
|
3544
|
+
//#region ---- Display rule row layout (result-kind aware) ----
|
|
3545
|
+
function buildDisplayRuleOperatorWidget(resultKind) {
|
|
3546
|
+
const dataSource = resultKind === 'boolean'
|
|
3547
|
+
? OUTCOME_DISPLAY_OPERATOR_BOOLEAN_SELECT_OPTIONS
|
|
3548
|
+
: resultKind === 'string'
|
|
3549
|
+
? OUTCOME_DISPLAY_OPERATOR_STRING_SELECT_OPTIONS
|
|
3550
|
+
: OUTCOME_DISPLAY_OPERATOR_SELECT_OPTIONS;
|
|
3551
|
+
return {
|
|
3552
|
+
type: AXPWidgetsCatalog.select,
|
|
3553
|
+
mode: 'edit',
|
|
3554
|
+
path: 'operator',
|
|
3555
|
+
name: 'operator',
|
|
3556
|
+
options: {
|
|
3557
|
+
valueField: 'id',
|
|
3558
|
+
textField: 'title',
|
|
3559
|
+
dataSource: [...dataSource],
|
|
3560
|
+
},
|
|
3561
|
+
};
|
|
3562
|
+
}
|
|
3563
|
+
function buildDisplayRuleCompareValueWidget(resultKind) {
|
|
3564
|
+
if (resultKind === 'boolean') {
|
|
3565
|
+
return {
|
|
3566
|
+
type: AXPWidgetsCatalog.toggle,
|
|
3567
|
+
mode: 'edit',
|
|
3568
|
+
path: 'compareValue',
|
|
3569
|
+
name: 'compareValue',
|
|
3570
|
+
options: {},
|
|
3571
|
+
};
|
|
3572
|
+
}
|
|
3573
|
+
if (resultKind === 'string') {
|
|
3574
|
+
return {
|
|
3575
|
+
type: AXPWidgetsCatalog.text,
|
|
3576
|
+
mode: 'edit',
|
|
3577
|
+
path: 'compareValue',
|
|
3578
|
+
name: 'compareValue',
|
|
3579
|
+
options: {
|
|
3580
|
+
placeholder: COMPARE_VALUE_PLACEHOLDER,
|
|
3581
|
+
},
|
|
3582
|
+
};
|
|
3583
|
+
}
|
|
3584
|
+
return {
|
|
3585
|
+
type: AXPWidgetsCatalog.number,
|
|
3586
|
+
mode: 'edit',
|
|
3587
|
+
path: 'compareValue',
|
|
3588
|
+
name: 'compareValue',
|
|
3589
|
+
options: {
|
|
3590
|
+
placeholder: COMPARE_VALUE_PLACEHOLDER,
|
|
3591
|
+
},
|
|
3592
|
+
};
|
|
3593
|
+
}
|
|
3594
|
+
function buildDisplayRuleRepeaterChildren(resultKind) {
|
|
3595
|
+
return [
|
|
3596
|
+
{
|
|
3597
|
+
type: AXPWidgetsCatalog.grid,
|
|
3598
|
+
mode: 'edit',
|
|
3599
|
+
options: {
|
|
3600
|
+
width: '100%',
|
|
3601
|
+
grid: {
|
|
3602
|
+
default: {
|
|
3603
|
+
columns: 12,
|
|
3604
|
+
gap: '8px',
|
|
3605
|
+
alignItems: 'center',
|
|
3606
|
+
},
|
|
3607
|
+
},
|
|
3608
|
+
},
|
|
3609
|
+
children: [
|
|
3610
|
+
{
|
|
3611
|
+
type: AXPWidgetsCatalog.gridItem,
|
|
3612
|
+
mode: 'edit',
|
|
3613
|
+
options: { colSpan: 3, ...DISPLAY_RULE_GRID_CELL },
|
|
3614
|
+
children: [buildDisplayRuleOperatorWidget(resultKind)],
|
|
3615
|
+
},
|
|
3616
|
+
{
|
|
3617
|
+
type: AXPWidgetsCatalog.gridItem,
|
|
3618
|
+
mode: 'edit',
|
|
3619
|
+
options: { colSpan: 2, ...DISPLAY_RULE_GRID_CELL },
|
|
3620
|
+
children: [buildDisplayRuleCompareValueWidget(resultKind)],
|
|
3621
|
+
},
|
|
3622
|
+
{
|
|
3623
|
+
type: AXPWidgetsCatalog.gridItem,
|
|
3624
|
+
mode: 'edit',
|
|
3625
|
+
options: { colSpan: 3, ...DISPLAY_RULE_GRID_CELL },
|
|
3626
|
+
children: [
|
|
3627
|
+
{
|
|
3628
|
+
type: AXPWidgetsCatalog.themeColorChooser,
|
|
3629
|
+
mode: 'edit',
|
|
3630
|
+
path: 'color',
|
|
3631
|
+
name: 'color',
|
|
3632
|
+
options: {
|
|
3633
|
+
placeholder: '@assessment-management:questionnaires.components.questionnaire-outcomes-builder.fields.display-color.placeholder',
|
|
3634
|
+
},
|
|
3635
|
+
},
|
|
3636
|
+
],
|
|
3637
|
+
},
|
|
3638
|
+
{
|
|
3639
|
+
type: AXPWidgetsCatalog.gridItem,
|
|
3640
|
+
mode: 'edit',
|
|
3641
|
+
options: { colSpan: 2, ...DISPLAY_RULE_GRID_CELL },
|
|
3642
|
+
children: [
|
|
3643
|
+
{
|
|
3644
|
+
type: AXPWidgetsCatalog.select,
|
|
3645
|
+
mode: 'edit',
|
|
3646
|
+
path: 'emphasis',
|
|
3647
|
+
name: 'emphasis',
|
|
3648
|
+
options: {
|
|
3649
|
+
valueField: 'id',
|
|
3650
|
+
textField: 'title',
|
|
3651
|
+
dataSource: [...OUTCOME_DISPLAY_EMPHASIS_SELECT_OPTIONS],
|
|
3652
|
+
},
|
|
3653
|
+
},
|
|
3654
|
+
],
|
|
3655
|
+
},
|
|
3656
|
+
{
|
|
3657
|
+
type: AXPWidgetsCatalog.gridItem,
|
|
3658
|
+
mode: 'edit',
|
|
3659
|
+
options: { colSpan: 2, ...DISPLAY_RULE_GRID_CELL },
|
|
3660
|
+
children: [
|
|
3661
|
+
{
|
|
3662
|
+
type: AXPWidgetsCatalog.iconChooser,
|
|
3663
|
+
mode: 'edit',
|
|
3664
|
+
path: 'icon',
|
|
3665
|
+
name: 'icon',
|
|
3666
|
+
options: {},
|
|
3667
|
+
},
|
|
3668
|
+
],
|
|
3669
|
+
},
|
|
3670
|
+
],
|
|
3671
|
+
},
|
|
3672
|
+
];
|
|
3673
|
+
}
|
|
3674
|
+
function buildDisplayRulesProps(resultKind) {
|
|
3675
|
+
return [
|
|
3676
|
+
{
|
|
3677
|
+
name: 'displayRules',
|
|
3678
|
+
title: '@assessment-management:questionnaires.components.questionnaire-outcomes-builder.fields.display-rules.title',
|
|
3679
|
+
description: '@assessment-management:questionnaires.components.questionnaire-outcomes-builder.fields.display-rules.description',
|
|
3680
|
+
group: GROUP_DISPLAY_RULES,
|
|
3681
|
+
order: 10,
|
|
3682
|
+
showLabel: false,
|
|
3683
|
+
schema: {
|
|
3684
|
+
dataType: 'array',
|
|
3685
|
+
defaultValue: [],
|
|
3686
|
+
nullable: true,
|
|
3687
|
+
interface: {
|
|
3688
|
+
name: 'displayRules',
|
|
3689
|
+
path: 'displayRules',
|
|
3690
|
+
type: AXPWidgetsCatalog.repeaterLayout,
|
|
3691
|
+
options: {
|
|
3692
|
+
hasControls: true,
|
|
3693
|
+
allowReorder: true,
|
|
3694
|
+
width: '100%',
|
|
3695
|
+
},
|
|
3696
|
+
children: buildDisplayRuleRepeaterChildren(resultKind),
|
|
3697
|
+
},
|
|
3698
|
+
},
|
|
3699
|
+
visible: true,
|
|
3700
|
+
},
|
|
3701
|
+
];
|
|
3702
|
+
}
|
|
3703
|
+
//#endregion
|
|
3704
|
+
//#region ---- Properties ----
|
|
3705
|
+
const BASIC_PROPS = [
|
|
3706
|
+
{
|
|
3707
|
+
name: 'name',
|
|
3708
|
+
title: '@assessment-management:questionnaires.components.questionnaire-outcomes-builder.fields.name.title',
|
|
3709
|
+
group: GROUP_BASIC,
|
|
3710
|
+
order: 10,
|
|
3711
|
+
schema: {
|
|
3712
|
+
dataType: 'string',
|
|
3713
|
+
defaultValue: '',
|
|
3714
|
+
interface: {
|
|
3715
|
+
name: 'name',
|
|
3716
|
+
path: 'name',
|
|
3717
|
+
type: AXPWidgetsCatalog.text,
|
|
3718
|
+
options: {
|
|
3719
|
+
placeholder: '@assessment-management:questionnaires.components.questionnaire-outcomes-builder.fields.name.placeholder',
|
|
3720
|
+
},
|
|
3721
|
+
},
|
|
3722
|
+
},
|
|
3723
|
+
validations: [{ rule: 'required' }, { rule: 'variable-name' }],
|
|
3724
|
+
visible: true,
|
|
3725
|
+
},
|
|
3726
|
+
{
|
|
3727
|
+
name: 'title',
|
|
3728
|
+
title: '@assessment-management:questionnaires.components.questionnaire-outcomes-builder.fields.title.title',
|
|
3729
|
+
group: GROUP_BASIC,
|
|
3730
|
+
order: 20,
|
|
3731
|
+
schema: {
|
|
3732
|
+
dataType: 'string',
|
|
3733
|
+
defaultValue: '',
|
|
3734
|
+
interface: {
|
|
3735
|
+
name: 'title',
|
|
3736
|
+
path: 'title',
|
|
3737
|
+
type: AXPWidgetsCatalog.text,
|
|
3738
|
+
options: {
|
|
3739
|
+
placeholder: '@assessment-management:questionnaires.components.questionnaire-outcomes-builder.fields.title.placeholder',
|
|
3740
|
+
},
|
|
3741
|
+
},
|
|
3742
|
+
},
|
|
3743
|
+
validations: [{ rule: 'required' }],
|
|
3744
|
+
visible: true,
|
|
3745
|
+
},
|
|
3746
|
+
{
|
|
3747
|
+
name: 'description',
|
|
3748
|
+
title: '@assessment-management:questionnaires.components.questionnaire-outcomes-builder.fields.description.title',
|
|
3749
|
+
group: GROUP_BASIC,
|
|
3750
|
+
order: 30,
|
|
3751
|
+
schema: {
|
|
3752
|
+
dataType: 'string',
|
|
3753
|
+
defaultValue: '',
|
|
3754
|
+
interface: {
|
|
3755
|
+
name: 'description',
|
|
3756
|
+
path: 'description',
|
|
3757
|
+
type: AXPWidgetsCatalog.largeText,
|
|
3758
|
+
options: {
|
|
3759
|
+
rows: 3,
|
|
3760
|
+
placeholder: '@assessment-management:questionnaires.components.questionnaire-outcomes-builder.fields.description.placeholder',
|
|
3761
|
+
},
|
|
3762
|
+
},
|
|
3763
|
+
},
|
|
3764
|
+
visible: true,
|
|
3765
|
+
},
|
|
3766
|
+
];
|
|
3767
|
+
const RESULT_PROPS = [
|
|
3768
|
+
{
|
|
3769
|
+
name: 'resultKind',
|
|
3770
|
+
title: '@assessment-management:questionnaires.components.questionnaire-outcomes-builder.fields.result-kind.title',
|
|
3771
|
+
group: GROUP_RESULT,
|
|
3772
|
+
order: 10,
|
|
3773
|
+
schema: {
|
|
3774
|
+
dataType: 'string',
|
|
3775
|
+
defaultValue: { id: 'number', title: RESULT_KIND_OPTIONS[0].title },
|
|
3776
|
+
interface: {
|
|
3777
|
+
name: 'resultKind',
|
|
3778
|
+
path: 'resultKind',
|
|
3779
|
+
type: AXPWidgetsCatalog.select,
|
|
3780
|
+
options: {
|
|
3781
|
+
valueField: 'id',
|
|
3782
|
+
textField: 'title',
|
|
3783
|
+
dataSource: [...RESULT_KIND_OPTIONS],
|
|
3784
|
+
},
|
|
3785
|
+
},
|
|
3786
|
+
},
|
|
3787
|
+
validations: [{ rule: 'required' }],
|
|
3788
|
+
visible: true,
|
|
3789
|
+
},
|
|
3790
|
+
{
|
|
3791
|
+
name: 'expression',
|
|
3792
|
+
title: '@assessment-management:questionnaires.components.questionnaire-outcomes-builder.fields.expression.title',
|
|
3793
|
+
group: GROUP_RESULT,
|
|
3794
|
+
order: 20,
|
|
3795
|
+
schema: {
|
|
3796
|
+
dataType: 'string',
|
|
3797
|
+
defaultValue: '',
|
|
3798
|
+
interface: {
|
|
3799
|
+
name: 'expression',
|
|
3800
|
+
path: 'expression',
|
|
3801
|
+
type: 'code-editor',
|
|
3802
|
+
options: {
|
|
3803
|
+
language: 'javascript',
|
|
3804
|
+
lineNumbers: true,
|
|
3805
|
+
height: 'min-h-72',
|
|
3806
|
+
placeholder: '@assessment-management:questionnaires.components.questionnaire-outcomes-builder.fields.expression.placeholder',
|
|
3807
|
+
},
|
|
3808
|
+
},
|
|
3809
|
+
},
|
|
3810
|
+
validations: [{ rule: 'required' }],
|
|
3811
|
+
visible: true,
|
|
3812
|
+
},
|
|
3813
|
+
];
|
|
3814
|
+
//#endregion
|
|
3815
|
+
//#region ---- Tabs ----
|
|
3816
|
+
/** Builds outcome edit tabs; display-rule value widgets match the selected result kind. */
|
|
3817
|
+
function buildQuestionnaireOutcomeEditTabs(resultKind = 'number') {
|
|
3818
|
+
return [
|
|
3819
|
+
{
|
|
3820
|
+
name: 'general',
|
|
3821
|
+
title: '@assessment-management:questionnaires.components.questionnaire-outcomes-builder.tabs.general.title',
|
|
3822
|
+
groups: [
|
|
3823
|
+
{
|
|
3824
|
+
name: GROUP_BASIC.name,
|
|
3825
|
+
title: GROUP_BASIC.title,
|
|
3826
|
+
isCollapsed: false,
|
|
3827
|
+
props: BASIC_PROPS,
|
|
3828
|
+
},
|
|
3829
|
+
{
|
|
3830
|
+
name: GROUP_RESULT.name,
|
|
3831
|
+
title: GROUP_RESULT.title,
|
|
3832
|
+
isCollapsed: false,
|
|
3833
|
+
props: RESULT_PROPS,
|
|
3834
|
+
},
|
|
3835
|
+
{
|
|
3836
|
+
name: GROUP_DISPLAY_RULES.name,
|
|
3837
|
+
title: GROUP_DISPLAY_RULES.title,
|
|
3838
|
+
isCollapsed: false,
|
|
3839
|
+
props: buildDisplayRulesProps(resultKind),
|
|
3840
|
+
},
|
|
3841
|
+
],
|
|
3842
|
+
},
|
|
3843
|
+
];
|
|
3844
|
+
}
|
|
3845
|
+
//#endregion
|
|
3846
|
+
|
|
3847
|
+
//#region ---- Imports ----
|
|
3848
|
+
//#endregion
|
|
3849
|
+
//#region ---- Mapping ----
|
|
3850
|
+
function outcomeItemToBuilderItem(item, index) {
|
|
3851
|
+
return {
|
|
3852
|
+
id: item.id,
|
|
3853
|
+
name: item.name,
|
|
3854
|
+
order: item.order ?? index,
|
|
3855
|
+
title: item.title,
|
|
3856
|
+
description: item.description,
|
|
3857
|
+
resultKind: item.resultKind,
|
|
3858
|
+
expression: item.expression,
|
|
3859
|
+
displayRules: item.displayRules,
|
|
3860
|
+
isNewlyAdded: item.isNewlyAdded,
|
|
3861
|
+
};
|
|
3862
|
+
}
|
|
3863
|
+
function builderItemToOutcomeItem(item, index) {
|
|
3864
|
+
return {
|
|
3865
|
+
id: String(item.id ?? item['name'] ?? AXPDataGenerator.uuid()),
|
|
3866
|
+
name: String(item['name'] ?? ''),
|
|
3867
|
+
title: item['title'],
|
|
3868
|
+
description: item['description'],
|
|
3869
|
+
resultKind: (item['resultKind'] ?? 'number'),
|
|
3870
|
+
expression: String(item['expression'] ?? ''),
|
|
3871
|
+
displayRules: item['displayRules'],
|
|
3872
|
+
order: item.order ?? index,
|
|
3873
|
+
isNewlyAdded: item['isNewlyAdded'] === true,
|
|
3874
|
+
};
|
|
3875
|
+
}
|
|
3876
|
+
function sectionToBuilderSection(section, index) {
|
|
3877
|
+
const name = section.name.trim() || `section-${index + 1}`;
|
|
3878
|
+
return {
|
|
3879
|
+
id: name,
|
|
3880
|
+
name,
|
|
3881
|
+
order: section.order ?? index,
|
|
3882
|
+
title: section.title,
|
|
3883
|
+
description: section.description,
|
|
3884
|
+
isNewlyAdded: section.isNewlyAdded,
|
|
3885
|
+
items: (section.items ?? []).map((item, itemIndex) => outcomeItemToBuilderItem(item, itemIndex)),
|
|
3886
|
+
};
|
|
3887
|
+
}
|
|
3888
|
+
function builderSectionToOutcomeSection(section, index) {
|
|
3889
|
+
const name = String(section['name'] ?? section.id ?? '').trim() || `section-${index + 1}`;
|
|
3890
|
+
return {
|
|
3891
|
+
name,
|
|
3892
|
+
title: section['title'],
|
|
3893
|
+
description: section['description'],
|
|
3894
|
+
order: section.order ?? index,
|
|
3895
|
+
isNewlyAdded: section['isNewlyAdded'] === true,
|
|
3896
|
+
items: section.items.map((item, itemIndex) => builderItemToOutcomeItem(item, itemIndex)),
|
|
3897
|
+
};
|
|
3898
|
+
}
|
|
3899
|
+
function outcomesValueToBuilderValue(value) {
|
|
3900
|
+
const normalized = normalizeQuestionnaireOutcomesValue(value);
|
|
3901
|
+
return {
|
|
3902
|
+
sections: normalized.sections.map((section, index) => sectionToBuilderSection(section, index)),
|
|
3903
|
+
};
|
|
3904
|
+
}
|
|
3905
|
+
function builderValueToOutcomesValue(value) {
|
|
3906
|
+
return {
|
|
3907
|
+
sections: value.sections.map((section, index) => builderSectionToOutcomeSection(section, index)),
|
|
3908
|
+
};
|
|
3909
|
+
}
|
|
3910
|
+
//#endregion
|
|
3911
|
+
|
|
3912
|
+
//#region ---- Imports ----
|
|
3913
|
+
//#endregion
|
|
3914
|
+
//#region ---- Helpers ----
|
|
3915
|
+
function normalizeOutcomeName(name) {
|
|
3916
|
+
return (name ?? '').trim();
|
|
3917
|
+
}
|
|
3918
|
+
function createDefaultOutcomeSection(order = 0) {
|
|
3919
|
+
return {
|
|
3920
|
+
name: `section-${Date.now()}`,
|
|
3921
|
+
title: 'New Section',
|
|
3922
|
+
order,
|
|
3923
|
+
items: [],
|
|
3924
|
+
isNewlyAdded: true,
|
|
3925
|
+
};
|
|
3926
|
+
}
|
|
3927
|
+
//#endregion
|
|
3928
|
+
|
|
3929
|
+
//#region ---- Imports ----
|
|
3930
|
+
//#endregion
|
|
3931
|
+
//#region ---- Component ----
|
|
3932
|
+
class AXMQuestionnaireOutcomesBuilderComponent {
|
|
3933
|
+
//#endregion
|
|
3934
|
+
//#region ---- Lifecycle ----
|
|
3935
|
+
constructor() {
|
|
3936
|
+
//#region ---- Inputs / Outputs ----
|
|
3937
|
+
this.value = input(null, ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
|
|
3938
|
+
this.readonly = input(false, ...(ngDevMode ? [{ debugName: "readonly" }] : /* istanbul ignore next */ []));
|
|
3939
|
+
this.showHeader = input(true, ...(ngDevMode ? [{ debugName: "showHeader" }] : /* istanbul ignore next */ []));
|
|
3940
|
+
this.valueChange = output();
|
|
3941
|
+
//#endregion
|
|
3942
|
+
//#region ---- Services ----
|
|
3943
|
+
this.propertyViewerService = inject(AXPPropertyViewerService);
|
|
3944
|
+
this.translationService = inject(AXTranslationService);
|
|
3945
|
+
this.toastService = inject(AXToastService);
|
|
3946
|
+
//#endregion
|
|
3947
|
+
//#region ---- View references ----
|
|
3948
|
+
this.standardRef = viewChild(AXPStandardSectionItemsBuilderComponent, ...(ngDevMode ? [{ debugName: "standardRef" }] : /* istanbul ignore next */ []));
|
|
3949
|
+
//#endregion
|
|
3950
|
+
//#region ---- State ----
|
|
3951
|
+
this.builderValue = signal({ sections: [] }, ...(ngDevMode ? [{ debugName: "builderValue" }] : /* istanbul ignore next */ []));
|
|
3952
|
+
//#endregion
|
|
3953
|
+
//#region ---- Computed ----
|
|
3954
|
+
this.standardConfig = computed(() => ({
|
|
3955
|
+
showSectionTechnicalName: true,
|
|
3956
|
+
minSectionCount: 1,
|
|
3957
|
+
texts: {
|
|
3958
|
+
addSection: '@assessment-management:questionnaires.components.questionnaire-outcomes-builder.actions.add-section.title',
|
|
3959
|
+
addItem: '@assessment-management:questionnaires.components.questionnaire-outcomes-builder.actions.add-outcome.title',
|
|
3960
|
+
emptySectionsTitle: '@assessment-management:questionnaires.components.questionnaire-outcomes-builder.empty.no-sections.title',
|
|
3961
|
+
emptySectionsDescription: '@assessment-management:questionnaires.components.questionnaire-outcomes-builder.empty.no-sections.description',
|
|
3962
|
+
emptyItemsTitle: '@assessment-management:questionnaires.components.questionnaire-outcomes-builder.empty.empty-section.title',
|
|
3963
|
+
emptyItemsDescription: '@assessment-management:questionnaires.components.questionnaire-outcomes-builder.empty.empty-section.description',
|
|
3964
|
+
},
|
|
3965
|
+
mapItemToView: (item, _section) => this.mapOutcomeItemToView(item),
|
|
3966
|
+
promptAddItems: (sectionId, value) => this.promptAddOutcome(sectionId, value),
|
|
3967
|
+
promptEditItem: (item, sectionId, value) => this.promptEditOutcome(item, sectionId, value),
|
|
3968
|
+
}), ...(ngDevMode ? [{ debugName: "standardConfig" }] : /* istanbul ignore next */ []));
|
|
3969
|
+
effect(() => {
|
|
3970
|
+
const next = normalizeQuestionnaireOutcomesValue(this.value());
|
|
3971
|
+
const mapped = outcomesValueToBuilderValue(next);
|
|
3972
|
+
untracked(() => this.builderValue.set(this.ensureMinOneSection(mapped)));
|
|
3973
|
+
});
|
|
3974
|
+
}
|
|
3975
|
+
//#endregion
|
|
3976
|
+
//#region ---- Public API ----
|
|
3977
|
+
/** Page header command: delegates to standard builder add-section dialog. */
|
|
3978
|
+
async addSection() {
|
|
3979
|
+
await this.standardRef()?.addSection();
|
|
3980
|
+
}
|
|
3981
|
+
//#endregion
|
|
3982
|
+
//#region ---- Builder handlers ----
|
|
3983
|
+
onBuilderValueChange(next) {
|
|
3984
|
+
const normalized = this.ensureMinOneSection(next);
|
|
3985
|
+
this.builderValue.set(normalized);
|
|
3986
|
+
this.valueChange.emit(builderValueToOutcomesValue(normalized));
|
|
3987
|
+
}
|
|
3988
|
+
//#endregion
|
|
3989
|
+
//#region ---- Item mapping ----
|
|
3990
|
+
mapOutcomeItemToView(item) {
|
|
3991
|
+
const outcome = item;
|
|
3992
|
+
const locale = this.translationService.getActiveLang() ?? 'en-US';
|
|
3993
|
+
const title = resolveMultiLanguageString(outcome.title, locale).trim();
|
|
3994
|
+
const description = resolveMultiLanguageString(outcome.description, locale).trim();
|
|
3995
|
+
const badges = [];
|
|
3996
|
+
const kind = this.coerceResultKind(outcome.resultKind);
|
|
3997
|
+
badges.push({
|
|
3998
|
+
text: resolveOutcomeResultKindLabel(kind, locale),
|
|
3999
|
+
variant: 'neutral',
|
|
4000
|
+
});
|
|
4001
|
+
return {
|
|
4002
|
+
icon: 'fa-light fa-calculator',
|
|
4003
|
+
title: title || outcome.name || '—',
|
|
4004
|
+
name: outcome.name,
|
|
4005
|
+
description: description || undefined,
|
|
4006
|
+
badges,
|
|
4007
|
+
};
|
|
4008
|
+
}
|
|
4009
|
+
//#endregion
|
|
4010
|
+
//#region ---- Prompts ----
|
|
4011
|
+
async promptAddOutcome(sectionId, value) {
|
|
4012
|
+
const section = value.sections.find((s) => s.id === sectionId);
|
|
4013
|
+
if (!section) {
|
|
4014
|
+
return null;
|
|
4015
|
+
}
|
|
4016
|
+
const takenNames = this.collectOutcomeNames(value);
|
|
4017
|
+
const defaultName = this.allocateOutcomeName(takenNames);
|
|
4018
|
+
const item = await this.openOutcomeDialog({
|
|
4019
|
+
mode: 'add',
|
|
4020
|
+
context: {
|
|
4021
|
+
name: defaultName,
|
|
4022
|
+
title: '',
|
|
4023
|
+
description: '',
|
|
4024
|
+
resultKind: toOutcomeResultKindSelectValue('number'),
|
|
4025
|
+
expression: '',
|
|
4026
|
+
displayRules: [],
|
|
4027
|
+
},
|
|
4028
|
+
sectionId,
|
|
4029
|
+
value,
|
|
4030
|
+
excludeItemId: undefined,
|
|
4031
|
+
});
|
|
4032
|
+
return item ? [item] : null;
|
|
4033
|
+
}
|
|
4034
|
+
async promptEditOutcome(item, sectionId, value) {
|
|
4035
|
+
const outcome = item;
|
|
4036
|
+
return this.openOutcomeDialog({
|
|
4037
|
+
mode: 'edit',
|
|
4038
|
+
context: {
|
|
4039
|
+
name: outcome.name,
|
|
4040
|
+
title: outcome.title ?? '',
|
|
4041
|
+
description: outcome.description ?? '',
|
|
4042
|
+
resultKind: toOutcomeResultKindSelectValue(this.coerceResultKind(outcome.resultKind)),
|
|
4043
|
+
expression: outcome.expression ?? '',
|
|
4044
|
+
displayRules: this.toDisplayRulesFormContext(outcome.displayRules),
|
|
4045
|
+
},
|
|
4046
|
+
sectionId,
|
|
4047
|
+
value,
|
|
4048
|
+
excludeItemId: item.id,
|
|
4049
|
+
existingItem: item,
|
|
4050
|
+
});
|
|
4051
|
+
}
|
|
4052
|
+
async openOutcomeDialog(options) {
|
|
4053
|
+
const validationFailed = async (titleKey, descKey, fallTitle, fallDesc) => {
|
|
4054
|
+
const title = (await this.translationService.translateAsync(titleKey)) || fallTitle;
|
|
4055
|
+
const content = (await this.translationService.translateAsync(descKey)) || fallDesc;
|
|
4056
|
+
this.toastService.show({ color: 'warning', title, content });
|
|
4057
|
+
throw new Error('QuestionnaireOutcomeEditValidation');
|
|
4058
|
+
};
|
|
4059
|
+
try {
|
|
4060
|
+
const titleKey = options.mode === 'add'
|
|
4061
|
+
? '@assessment-management:questionnaires.components.questionnaire-outcomes-builder.actions.add-outcome.title'
|
|
4062
|
+
: '@general:actions.edit.title';
|
|
4063
|
+
const initialResultKind = this.coerceResultKind(options.context.resultKind);
|
|
4064
|
+
const result = await this.propertyViewerService
|
|
4065
|
+
.create()
|
|
4066
|
+
.dialog((d) => {
|
|
4067
|
+
d.setTitle(titleKey)
|
|
4068
|
+
.setSize('lg')
|
|
4069
|
+
.setCloseButton(true)
|
|
4070
|
+
.setMode('advanced')
|
|
4071
|
+
.setTabs(buildQuestionnaireOutcomeEditTabs(initialResultKind))
|
|
4072
|
+
.setContext(options.context)
|
|
4073
|
+
.onAction(async (ref) => {
|
|
4074
|
+
const context = ref.context();
|
|
4075
|
+
const rawName = normalizeOutcomeName(context.name);
|
|
4076
|
+
if (!rawName) {
|
|
4077
|
+
await validationFailed('@assessment-management:questionnaires.components.questionnaire-outcomes-builder.validation.name-required.title', '@assessment-management:questionnaires.components.questionnaire-outcomes-builder.validation.name-required.description', 'Name required', 'Enter a unique outcome name.');
|
|
4078
|
+
}
|
|
4079
|
+
if (!/^[a-zA-Z][a-zA-Z0-9_-]*$/.test(rawName)) {
|
|
4080
|
+
await validationFailed('@assessment-management:questionnaires.components.questionnaire-outcomes-builder.validation.name-invalid.title', '@assessment-management:questionnaires.components.questionnaire-outcomes-builder.validation.name-invalid.description', 'Invalid name', 'Use letters, numbers, underscores, and hyphens.');
|
|
4081
|
+
}
|
|
4082
|
+
const taken = this.collectOutcomeNames(options.value, options.excludeItemId);
|
|
4083
|
+
if (taken.has(rawName)) {
|
|
4084
|
+
await validationFailed('@assessment-management:questionnaires.components.questionnaire-outcomes-builder.validation.duplicate-name', '@assessment-management:questionnaires.components.questionnaire-outcomes-builder.validation.duplicate-name', 'Duplicate name', 'Another outcome already uses this name.');
|
|
4085
|
+
}
|
|
4086
|
+
const title = context.title;
|
|
4087
|
+
if (isEffectivelyEmptyLocalizedValue(title)) {
|
|
4088
|
+
await validationFailed('@assessment-management:questionnaires.components.questionnaire-outcomes-builder.validation.title-required.title', '@assessment-management:questionnaires.components.questionnaire-outcomes-builder.validation.title-required.description', 'Title required', 'Enter a display title for this outcome.');
|
|
4089
|
+
}
|
|
4090
|
+
const expression = String(context.expression ?? '').trim();
|
|
4091
|
+
if (!expression) {
|
|
4092
|
+
await validationFailed('@assessment-management:questionnaires.components.questionnaire-outcomes-builder.validation.expression-required.title', '@assessment-management:questionnaires.components.questionnaire-outcomes-builder.validation.expression-required.description', 'Expression required', 'Enter an expression for this outcome.');
|
|
4093
|
+
}
|
|
4094
|
+
});
|
|
4095
|
+
})
|
|
4096
|
+
.show();
|
|
4097
|
+
if (!result) {
|
|
4098
|
+
return null;
|
|
4099
|
+
}
|
|
4100
|
+
const form = result.values;
|
|
4101
|
+
const name = normalizeOutcomeName(form.name);
|
|
4102
|
+
const title = this.normalizeLocalizedField(form.title);
|
|
4103
|
+
const description = this.normalizeLocalizedField(form.description);
|
|
4104
|
+
const resultKind = this.coerceResultKind(form.resultKind);
|
|
4105
|
+
const expression = String(form.expression ?? '').trim();
|
|
4106
|
+
const displayRules = this.normalizeDisplayRulesFromForm(form.displayRules, resultKind);
|
|
4107
|
+
const id = options.mode === 'edit' && options.existingItem
|
|
4108
|
+
? String(options.existingItem.id)
|
|
4109
|
+
: AXPDataGenerator.uuid();
|
|
4110
|
+
return {
|
|
4111
|
+
...(options.existingItem ?? {}),
|
|
4112
|
+
id,
|
|
4113
|
+
name,
|
|
4114
|
+
title,
|
|
4115
|
+
description,
|
|
4116
|
+
resultKind,
|
|
4117
|
+
expression,
|
|
4118
|
+
displayRules,
|
|
4119
|
+
order: options.existingItem?.order ?? 0,
|
|
4120
|
+
isNewlyAdded: options.mode === 'add',
|
|
4121
|
+
};
|
|
4122
|
+
}
|
|
4123
|
+
catch (error) {
|
|
4124
|
+
if (error instanceof Error && error.message === 'QuestionnaireOutcomeEditValidation') {
|
|
4125
|
+
return null;
|
|
4126
|
+
}
|
|
4127
|
+
console.error('Error editing outcome:', error);
|
|
4128
|
+
return null;
|
|
4129
|
+
}
|
|
4130
|
+
}
|
|
4131
|
+
//#endregion
|
|
4132
|
+
//#region ---- Utility ----
|
|
4133
|
+
ensureMinOneSection(value) {
|
|
4134
|
+
if (value.sections.length > 0) {
|
|
4135
|
+
return value;
|
|
4136
|
+
}
|
|
4137
|
+
const section = createDefaultOutcomeSection(0);
|
|
4138
|
+
return outcomesValueToBuilderValue({ sections: [section] });
|
|
4139
|
+
}
|
|
4140
|
+
collectOutcomeNames(value, excludeItemId) {
|
|
4141
|
+
const names = new Set();
|
|
4142
|
+
for (const section of value.sections) {
|
|
4143
|
+
for (const item of section.items) {
|
|
4144
|
+
if (excludeItemId != null && item.id === excludeItemId) {
|
|
4145
|
+
continue;
|
|
4146
|
+
}
|
|
4147
|
+
const name = normalizeOutcomeName(String(item['name'] ?? ''));
|
|
4148
|
+
if (name) {
|
|
4149
|
+
names.add(name);
|
|
4150
|
+
}
|
|
4151
|
+
}
|
|
4152
|
+
}
|
|
4153
|
+
return names;
|
|
4154
|
+
}
|
|
4155
|
+
allocateOutcomeName(taken) {
|
|
4156
|
+
let index = taken.size + 1;
|
|
4157
|
+
let name = `outcome_${index}`;
|
|
4158
|
+
while (taken.has(name)) {
|
|
4159
|
+
index += 1;
|
|
4160
|
+
name = `outcome_${index}`;
|
|
4161
|
+
}
|
|
4162
|
+
return name;
|
|
4163
|
+
}
|
|
4164
|
+
coerceResultKind(value) {
|
|
4165
|
+
if (value === 'number' || value === 'string' || value === 'boolean') {
|
|
4166
|
+
return value;
|
|
4167
|
+
}
|
|
4168
|
+
if (value != null && typeof value === 'object' && 'id' in value) {
|
|
4169
|
+
const id = value.id;
|
|
4170
|
+
if (id === 'number' || id === 'string' || id === 'boolean') {
|
|
4171
|
+
return id;
|
|
4172
|
+
}
|
|
4173
|
+
}
|
|
4174
|
+
return 'number';
|
|
4175
|
+
}
|
|
4176
|
+
coerceDisplayOperator(value, resultKind) {
|
|
4177
|
+
let operator;
|
|
4178
|
+
if (value === 'eq' || value === 'neq' || value === 'gt' || value === 'gte' || value === 'lt' || value === 'lte') {
|
|
4179
|
+
operator = value;
|
|
4180
|
+
}
|
|
4181
|
+
else if (value != null && typeof value === 'object' && 'id' in value) {
|
|
4182
|
+
const id = value.id;
|
|
4183
|
+
if (id === 'eq' || id === 'neq' || id === 'gt' || id === 'gte' || id === 'lt' || id === 'lte') {
|
|
4184
|
+
operator = id;
|
|
4185
|
+
}
|
|
4186
|
+
}
|
|
4187
|
+
if (resultKind === 'boolean') {
|
|
4188
|
+
return operator === 'eq' || operator === 'neq' ? operator : 'eq';
|
|
4189
|
+
}
|
|
4190
|
+
if (resultKind === 'string') {
|
|
4191
|
+
return operator === 'eq' || operator === 'neq' ? operator : 'eq';
|
|
4192
|
+
}
|
|
4193
|
+
return operator ?? 'gte';
|
|
4194
|
+
}
|
|
4195
|
+
coerceDisplayCompareValue(value, resultKind) {
|
|
4196
|
+
if (resultKind === 'boolean') {
|
|
4197
|
+
if (typeof value === 'boolean') {
|
|
4198
|
+
return value;
|
|
4199
|
+
}
|
|
4200
|
+
if (value === 'true') {
|
|
4201
|
+
return true;
|
|
4202
|
+
}
|
|
4203
|
+
if (value === 'false') {
|
|
4204
|
+
return false;
|
|
4205
|
+
}
|
|
4206
|
+
return undefined;
|
|
4207
|
+
}
|
|
4208
|
+
if (resultKind === 'number') {
|
|
4209
|
+
if (typeof value === 'number' && Number.isFinite(value)) {
|
|
4210
|
+
return value;
|
|
4211
|
+
}
|
|
4212
|
+
if (typeof value === 'string') {
|
|
4213
|
+
const trimmed = value.trim();
|
|
4214
|
+
if (!trimmed) {
|
|
4215
|
+
return undefined;
|
|
4216
|
+
}
|
|
4217
|
+
const asNumber = Number(trimmed);
|
|
4218
|
+
return Number.isFinite(asNumber) ? asNumber : undefined;
|
|
4219
|
+
}
|
|
4220
|
+
return undefined;
|
|
4221
|
+
}
|
|
4222
|
+
if (typeof value === 'string') {
|
|
4223
|
+
const trimmed = value.trim();
|
|
4224
|
+
return trimmed.length > 0 ? trimmed : undefined;
|
|
4225
|
+
}
|
|
4226
|
+
if (typeof value === 'number' && Number.isFinite(value)) {
|
|
4227
|
+
return String(value);
|
|
4228
|
+
}
|
|
4229
|
+
if (typeof value === 'boolean') {
|
|
4230
|
+
return value ? 'true' : 'false';
|
|
4231
|
+
}
|
|
4232
|
+
return undefined;
|
|
4233
|
+
}
|
|
4234
|
+
normalizeDisplayColorValue(value) {
|
|
4235
|
+
if (typeof value !== 'string') {
|
|
4236
|
+
return undefined;
|
|
4237
|
+
}
|
|
4238
|
+
const trimmed = value.trim();
|
|
4239
|
+
const parts = trimmed.split(/\s+/);
|
|
4240
|
+
if (parts.length !== 3) {
|
|
4241
|
+
return undefined;
|
|
4242
|
+
}
|
|
4243
|
+
return trimmed;
|
|
4244
|
+
}
|
|
4245
|
+
coerceDisplayEmphasis(value) {
|
|
4246
|
+
if (value === 'normal' || value === 'medium' || value === 'bold') {
|
|
4247
|
+
return value;
|
|
4248
|
+
}
|
|
4249
|
+
if (value != null && typeof value === 'object' && 'id' in value) {
|
|
4250
|
+
const id = value.id;
|
|
4251
|
+
if (id === 'normal' || id === 'medium' || id === 'bold') {
|
|
4252
|
+
return id;
|
|
4253
|
+
}
|
|
4254
|
+
}
|
|
4255
|
+
return 'normal';
|
|
4256
|
+
}
|
|
4257
|
+
normalizeDisplayIconValue(value) {
|
|
4258
|
+
if (value == null || value === '') {
|
|
4259
|
+
return undefined;
|
|
4260
|
+
}
|
|
4261
|
+
if (typeof value === 'string') {
|
|
4262
|
+
const trimmed = value.trim();
|
|
4263
|
+
return trimmed.length > 0 ? trimmed : undefined;
|
|
4264
|
+
}
|
|
4265
|
+
if (typeof value === 'object') {
|
|
4266
|
+
const styleClass = String(get(value, 'styleClass') ?? '').trim();
|
|
4267
|
+
const iconClass = String(get(value, 'iconClass') ?? '').trim();
|
|
4268
|
+
const combined = [styleClass, iconClass].filter(Boolean).join(' ');
|
|
4269
|
+
return combined.length > 0 ? combined : undefined;
|
|
4270
|
+
}
|
|
4271
|
+
return undefined;
|
|
4272
|
+
}
|
|
4273
|
+
toDisplayRulesFormContext(rules) {
|
|
4274
|
+
return normalizeQuestionnaireOutcomeDisplayRules(rules).map((rule) => ({
|
|
4275
|
+
id: rule.id,
|
|
4276
|
+
operator: toOutcomeDisplayOperatorSelectValue(rule.operator),
|
|
4277
|
+
compareValue: rule.compareValue,
|
|
4278
|
+
color: rule.color,
|
|
4279
|
+
emphasis: toOutcomeDisplayEmphasisSelectValue(rule.emphasis ?? 'normal'),
|
|
4280
|
+
icon: rule.icon,
|
|
4281
|
+
}));
|
|
4282
|
+
}
|
|
4283
|
+
normalizeDisplayRulesFromForm(raw, resultKind) {
|
|
4284
|
+
if (!Array.isArray(raw)) {
|
|
4285
|
+
return [];
|
|
4286
|
+
}
|
|
4287
|
+
const rows = [];
|
|
4288
|
+
for (const [index, row] of raw.entries()) {
|
|
4289
|
+
const compareValue = this.coerceDisplayCompareValue(get(row, 'compareValue'), resultKind);
|
|
4290
|
+
const color = this.normalizeDisplayColorValue(get(row, 'color'));
|
|
4291
|
+
if (compareValue === undefined || !color) {
|
|
4292
|
+
continue;
|
|
4293
|
+
}
|
|
4294
|
+
rows.push({
|
|
4295
|
+
id: String(get(row, 'id') ?? AXPDataGenerator.uuid()),
|
|
4296
|
+
order: index,
|
|
4297
|
+
operator: this.coerceDisplayOperator(get(row, 'operator'), resultKind),
|
|
4298
|
+
compareValue,
|
|
4299
|
+
color,
|
|
4300
|
+
emphasis: this.coerceDisplayEmphasis(get(row, 'emphasis')),
|
|
4301
|
+
icon: this.normalizeDisplayIconValue(get(row, 'icon')),
|
|
4302
|
+
});
|
|
4303
|
+
}
|
|
4304
|
+
return normalizeQuestionnaireOutcomeDisplayRules(rows);
|
|
4305
|
+
}
|
|
4306
|
+
normalizeLocalizedField(value) {
|
|
4307
|
+
if (value == null || value === '') {
|
|
4308
|
+
return undefined;
|
|
4309
|
+
}
|
|
4310
|
+
if (typeof value === 'string') {
|
|
4311
|
+
const trimmed = value.trim();
|
|
4312
|
+
return trimmed ? createMultiLanguageString(trimmed, trimmed) : undefined;
|
|
4313
|
+
}
|
|
4314
|
+
if (typeof value === 'object') {
|
|
4315
|
+
return value;
|
|
4316
|
+
}
|
|
4317
|
+
return undefined;
|
|
4318
|
+
}
|
|
4319
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMQuestionnaireOutcomesBuilderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
4320
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: AXMQuestionnaireOutcomesBuilderComponent, isStandalone: true, selector: "axm-questionnaire-outcomes-builder", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, showHeader: { classPropertyName: "showHeader", publicName: "showHeader", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { valueChange: "valueChange" }, viewQueries: [{ propertyName: "standardRef", first: true, predicate: AXPStandardSectionItemsBuilderComponent, descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"axm-questionnaire-outcomes-builder\">\n @if (showHeader()) {\n <div class=\"__header\">\n <div class=\"__header-left\"></div>\n <div class=\"__header-right\">\n @if (!readonly()) {\n <ax-button\n class=\"ax-sm\"\n [text]=\"\n ('@assessment-management:questionnaires.components.questionnaire-outcomes-builder.actions.add-section.title'\n | translate\n | async) || 'Add Section'\n \"\n [color]=\"'primary'\"\n (onClick)=\"addSection()\">\n <ax-prefix>\n <ax-icon icon=\"fa-light fa-layer-group\"></ax-icon>\n </ax-prefix>\n </ax-button>\n }\n </div>\n </div>\n }\n\n <axp-standard-section-items-builder\n #standardRef\n class=\"ax-block ax-min-h-[200px]\"\n [value]=\"builderValue()\"\n [config]=\"standardConfig()\"\n [readonly]=\"readonly()\"\n (valueChange)=\"onBuilderValueChange($event)\" />\n</div>\n", styles: [".axm-questionnaire-outcomes-builder{display:flex;height:100%;width:100%;flex-direction:column}.axm-questionnaire-outcomes-builder .__header{display:flex;align-items:center;justify-content:space-between;gap:.75rem;border-bottom-width:1px;padding:.75rem}.axm-questionnaire-outcomes-builder .__header .__header-left,.axm-questionnaire-outcomes-builder .__header .__header-right{display:flex;gap:.5rem}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i1.AXButtonComponent, selector: "ax-button", inputs: ["disabled", "size", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i2.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i2.AXDecoratorGenericComponent, selector: "ax-footer, ax-header, ax-content, ax-divider, ax-form-hint, ax-prefix, ax-suffix, ax-text, ax-title, ax-subtitle, ax-placeholder, ax-overlay" }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "component", type: AXPStandardSectionItemsBuilderComponent, selector: "axp-standard-section-items-builder", inputs: ["value", "config", "readonly"], outputs: ["valueChange"] }, { kind: "pipe", type: i3.AsyncPipe, name: "async" }, { kind: "pipe", type: i4.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
4321
|
+
}
|
|
4322
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMQuestionnaireOutcomesBuilderComponent, decorators: [{
|
|
4323
|
+
type: Component,
|
|
4324
|
+
args: [{ selector: 'axm-questionnaire-outcomes-builder', changeDetection: ChangeDetectionStrategy.OnPush, imports: [
|
|
4325
|
+
CommonModule,
|
|
4326
|
+
AXButtonModule,
|
|
4327
|
+
AXDecoratorModule,
|
|
4328
|
+
AXTranslationModule,
|
|
4329
|
+
AXPStandardSectionItemsBuilderComponent,
|
|
4330
|
+
], template: "<div class=\"axm-questionnaire-outcomes-builder\">\n @if (showHeader()) {\n <div class=\"__header\">\n <div class=\"__header-left\"></div>\n <div class=\"__header-right\">\n @if (!readonly()) {\n <ax-button\n class=\"ax-sm\"\n [text]=\"\n ('@assessment-management:questionnaires.components.questionnaire-outcomes-builder.actions.add-section.title'\n | translate\n | async) || 'Add Section'\n \"\n [color]=\"'primary'\"\n (onClick)=\"addSection()\">\n <ax-prefix>\n <ax-icon icon=\"fa-light fa-layer-group\"></ax-icon>\n </ax-prefix>\n </ax-button>\n }\n </div>\n </div>\n }\n\n <axp-standard-section-items-builder\n #standardRef\n class=\"ax-block ax-min-h-[200px]\"\n [value]=\"builderValue()\"\n [config]=\"standardConfig()\"\n [readonly]=\"readonly()\"\n (valueChange)=\"onBuilderValueChange($event)\" />\n</div>\n", styles: [".axm-questionnaire-outcomes-builder{display:flex;height:100%;width:100%;flex-direction:column}.axm-questionnaire-outcomes-builder .__header{display:flex;align-items:center;justify-content:space-between;gap:.75rem;border-bottom-width:1px;padding:.75rem}.axm-questionnaire-outcomes-builder .__header .__header-left,.axm-questionnaire-outcomes-builder .__header .__header-right{display:flex;gap:.5rem}\n"] }]
|
|
4331
|
+
}], ctorParameters: () => [], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], showHeader: [{ type: i0.Input, args: [{ isSignal: true, alias: "showHeader", required: false }] }], valueChange: [{ type: i0.Output, args: ["valueChange"] }], standardRef: [{ type: i0.ViewChild, args: [i0.forwardRef(() => AXPStandardSectionItemsBuilderComponent), { isSignal: true }] }] } });
|
|
4332
|
+
|
|
4333
|
+
/** Component key for the questionnaire Outcomes page tab. Register via AXP_PAGE_COMPONENT_PROVIDER. */
|
|
4334
|
+
const QUESTIONNAIRE_OUTCOMES_PAGE_COMPONENT_KEY = 'questionnaire-outcomes-page';
|
|
4335
|
+
|
|
4336
|
+
const QUESTIONNAIRE_OUTCOMES_SAVE_COMMAND = 'Questionnaire:Outcomes:Save';
|
|
4337
|
+
/**
|
|
4338
|
+
* Command to save the questionnaire outcomes field.
|
|
4339
|
+
* Patches entity with { outcomes }.
|
|
4340
|
+
*/
|
|
4341
|
+
class AXMSaveQuestionnaireOutcomesCommand {
|
|
4342
|
+
constructor() {
|
|
4343
|
+
this.entityService = inject(AXPEntityService);
|
|
4344
|
+
this.translationService = inject(AXTranslationService);
|
|
4345
|
+
}
|
|
4346
|
+
async execute(input) {
|
|
4347
|
+
const { id, outcomes } = input;
|
|
4348
|
+
if (!id) {
|
|
4349
|
+
return {
|
|
4350
|
+
success: false,
|
|
4351
|
+
message: {
|
|
4352
|
+
text: await this.translationService.translateAsync('@general:messages.entity.invalid-data'),
|
|
4353
|
+
},
|
|
4354
|
+
};
|
|
4355
|
+
}
|
|
4356
|
+
try {
|
|
4357
|
+
const entityRef = `${RootConfig.module.name}.${RootConfig.entities.questionnaire.name}`;
|
|
4358
|
+
const dataAccessor = this.entityService.withEntity(entityRef).data();
|
|
4359
|
+
await dataAccessor.update(id, { outcomes });
|
|
4360
|
+
return {
|
|
4361
|
+
success: true,
|
|
4362
|
+
data: { id, outcomes },
|
|
4363
|
+
message: {
|
|
4364
|
+
text: await this.translationService.translateAsync('@general:messages.generic.success.description'),
|
|
4365
|
+
},
|
|
4366
|
+
};
|
|
4367
|
+
}
|
|
4368
|
+
catch (error) {
|
|
4369
|
+
const message = error instanceof Error
|
|
4370
|
+
? error.message
|
|
4371
|
+
: await this.translationService.translateAsync('@general:messages.generic.error.description');
|
|
4372
|
+
return {
|
|
4373
|
+
success: false,
|
|
4374
|
+
message: { text: message },
|
|
4375
|
+
};
|
|
4376
|
+
}
|
|
4377
|
+
}
|
|
4378
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMSaveQuestionnaireOutcomesCommand, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
4379
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMSaveQuestionnaireOutcomesCommand, providedIn: 'root' }); }
|
|
4380
|
+
}
|
|
4381
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMSaveQuestionnaireOutcomesCommand, decorators: [{
|
|
4382
|
+
type: Injectable,
|
|
4383
|
+
args: [{
|
|
4384
|
+
providedIn: 'root',
|
|
4385
|
+
}]
|
|
4386
|
+
}] });
|
|
4387
|
+
|
|
4388
|
+
var saveQuestionnaireOutcomes_command = /*#__PURE__*/Object.freeze({
|
|
4389
|
+
__proto__: null,
|
|
4390
|
+
AXMSaveQuestionnaireOutcomesCommand: AXMSaveQuestionnaireOutcomesCommand,
|
|
4391
|
+
QUESTIONNAIRE_OUTCOMES_SAVE_COMMAND: QUESTIONNAIRE_OUTCOMES_SAVE_COMMAND
|
|
4392
|
+
});
|
|
4393
|
+
|
|
4394
|
+
const QUESTIONNAIRE_OUTCOMES_DISCARD_COMMAND = 'Questionnaire:Outcomes:Discard';
|
|
4395
|
+
const QUESTIONNAIRE_OUTCOMES_ADD_SECTION_COMMAND = 'Questionnaire:Outcomes:AddSection';
|
|
4396
|
+
//#region ---- Questionnaire Outcomes Page Component ----
|
|
4397
|
+
class AXMQuestionnaireOutcomesPageComponent extends AXPPageLayoutBaseComponent {
|
|
4398
|
+
//#endregion
|
|
4399
|
+
//#region ---- Lifecycle ----
|
|
4400
|
+
constructor() {
|
|
4401
|
+
super();
|
|
4402
|
+
//#region ---- Inputs ----
|
|
4403
|
+
this.rootContext = input(...(ngDevMode ? [undefined, { debugName: "rootContext" }] : /* istanbul ignore next */ []));
|
|
4404
|
+
this.pageConfig = input(...(ngDevMode ? [undefined, { debugName: "pageConfig" }] : /* istanbul ignore next */ []));
|
|
4405
|
+
//#endregion
|
|
4406
|
+
//#region ---- Services ----
|
|
4407
|
+
this.commandService = inject(AXPCommandService);
|
|
4408
|
+
this.eventService = inject(AXPBroadcastEventService);
|
|
4409
|
+
this.hostPageLayout = inject(AXPPageLayoutBase, { optional: true, skipSelf: true });
|
|
4410
|
+
//#endregion
|
|
4411
|
+
//#region ---- View References ----
|
|
4412
|
+
this.builderRef = viewChild('builderRef', ...(ngDevMode ? [{ debugName: "builderRef" }] : /* istanbul ignore next */ []));
|
|
4413
|
+
//#endregion
|
|
4414
|
+
//#region ---- State ----
|
|
4415
|
+
this.localContext = signal(null, ...(ngDevMode ? [{ debugName: "localContext" }] : /* istanbul ignore next */ []));
|
|
4416
|
+
this.ignoreNextValueChange = signal(false, ...(ngDevMode ? [{ debugName: "ignoreNextValueChange" }] : /* istanbul ignore next */ []));
|
|
4417
|
+
this.baselineOutcomes = signal(null, ...(ngDevMode ? [{ debugName: "baselineOutcomes" }] : /* istanbul ignore next */ []));
|
|
4418
|
+
this.outcomesBaselinePendingReconcile = signal(false, ...(ngDevMode ? [{ debugName: "outcomesBaselinePendingReconcile" }] : /* istanbul ignore next */ []));
|
|
4419
|
+
this.isDirty = signal(false, ...(ngDevMode ? [{ debugName: "isDirty" }] : /* istanbul ignore next */ []));
|
|
4420
|
+
//#endregion
|
|
4421
|
+
//#region ---- Computed ----
|
|
4422
|
+
this.context = computed(() => {
|
|
4423
|
+
const local = this.localContext();
|
|
4424
|
+
if (local != null)
|
|
4425
|
+
return local;
|
|
4426
|
+
return this.rootContext() ?? {};
|
|
4427
|
+
}, ...(ngDevMode ? [{ debugName: "context" }] : /* istanbul ignore next */ []));
|
|
4428
|
+
this.outcomesValue = computed(() => {
|
|
4429
|
+
const ctx = this.context();
|
|
4430
|
+
return normalizeQuestionnaireOutcomesValue(ctx['outcomes']);
|
|
4431
|
+
}, ...(ngDevMode ? [{ debugName: "outcomesValue" }] : /* istanbul ignore next */ []));
|
|
4432
|
+
let previousRootId = undefined;
|
|
4433
|
+
effect(() => {
|
|
4434
|
+
const ctx = this.rootContext();
|
|
4435
|
+
const currentId = ctx != null && typeof ctx === 'object' ? ctx['id'] : undefined;
|
|
4436
|
+
if (currentId !== previousRootId) {
|
|
4437
|
+
previousRootId = currentId;
|
|
4438
|
+
this.localContext.set(null);
|
|
4439
|
+
const rootOutcomes = normalizeQuestionnaireOutcomesValue(ctx?.['outcomes']);
|
|
4440
|
+
this.baselineOutcomes.set(this.cloneOutcomes(rootOutcomes));
|
|
4441
|
+
this.isDirty.set(false);
|
|
4442
|
+
this.outcomesBaselinePendingReconcile.set(true);
|
|
4443
|
+
}
|
|
4444
|
+
});
|
|
4445
|
+
}
|
|
4446
|
+
//#endregion
|
|
4447
|
+
//#region ---- Page Actions ----
|
|
4448
|
+
async getPrimaryMenuItems() {
|
|
4449
|
+
const addSectionTitle = (await this.translateService.translateAsync('@assessment-management:questionnaires.components.questionnaire-outcomes-builder.actions.add-section.title')) || 'Add Section';
|
|
4450
|
+
const discardTitle = (await this.translateService.translateAsync('@general:actions.discard.title')) || 'Discard';
|
|
4451
|
+
const saveTitle = (await this.translateService.translateAsync('@general:actions.save.title')) || 'Save';
|
|
4452
|
+
const addSectionAction = {
|
|
4453
|
+
title: addSectionTitle,
|
|
4454
|
+
icon: 'fa-light fa-layer-group',
|
|
4455
|
+
zone: 'header',
|
|
4456
|
+
priority: 'primary',
|
|
4457
|
+
color: 'primary',
|
|
4458
|
+
command: {
|
|
4459
|
+
name: QUESTIONNAIRE_OUTCOMES_ADD_SECTION_COMMAND,
|
|
4460
|
+
options: {},
|
|
4461
|
+
},
|
|
4462
|
+
};
|
|
4463
|
+
const discardAction = {
|
|
4464
|
+
title: discardTitle,
|
|
4465
|
+
icon: 'fa-light fa-rotate-left',
|
|
4466
|
+
zone: 'footer',
|
|
4467
|
+
priority: 'secondary',
|
|
4468
|
+
color: 'default',
|
|
4469
|
+
visible: this.isDirty(),
|
|
4470
|
+
command: {
|
|
4471
|
+
name: QUESTIONNAIRE_OUTCOMES_DISCARD_COMMAND,
|
|
4472
|
+
options: {},
|
|
4473
|
+
},
|
|
4474
|
+
};
|
|
4475
|
+
const saveAction = {
|
|
4476
|
+
title: saveTitle,
|
|
4477
|
+
icon: 'fa-light fa-floppy-disk',
|
|
4478
|
+
zone: 'footer',
|
|
4479
|
+
priority: 'primary',
|
|
4480
|
+
color: 'primary',
|
|
4481
|
+
visible: this.isDirty(),
|
|
4482
|
+
command: {
|
|
4483
|
+
name: QUESTIONNAIRE_OUTCOMES_SAVE_COMMAND,
|
|
4484
|
+
options: {},
|
|
4485
|
+
},
|
|
4486
|
+
};
|
|
4487
|
+
return [addSectionAction, discardAction, saveAction];
|
|
4488
|
+
}
|
|
4489
|
+
//#endregion
|
|
4490
|
+
//#region ---- Command Handling ----
|
|
4491
|
+
execute(command) {
|
|
4492
|
+
if (command.name === QUESTIONNAIRE_OUTCOMES_DISCARD_COMMAND) {
|
|
4493
|
+
this.ignoreNextValueChange.set(true);
|
|
4494
|
+
this.localContext.set(null);
|
|
4495
|
+
this.isDirty.set(false);
|
|
4496
|
+
this.outcomesBaselinePendingReconcile.set(true);
|
|
4497
|
+
this.recompute();
|
|
4498
|
+
return;
|
|
4499
|
+
}
|
|
4500
|
+
if (command.name === QUESTIONNAIRE_OUTCOMES_ADD_SECTION_COMMAND) {
|
|
4501
|
+
void this.builderRef()?.addSection();
|
|
4502
|
+
return;
|
|
4503
|
+
}
|
|
4504
|
+
if (command.name !== QUESTIONNAIRE_OUTCOMES_SAVE_COMMAND) {
|
|
4505
|
+
return;
|
|
4506
|
+
}
|
|
4507
|
+
return this.handleSaveExecute();
|
|
4508
|
+
}
|
|
4509
|
+
async handleSaveExecute() {
|
|
4510
|
+
const ctx = this.localContext() ?? this.rootContext() ?? {};
|
|
4511
|
+
const id = typeof ctx['id'] === 'string' ? ctx['id'] : undefined;
|
|
4512
|
+
const outcomes = normalizeQuestionnaireOutcomesValue(ctx['outcomes']);
|
|
4513
|
+
if (!id) {
|
|
4514
|
+
return {
|
|
4515
|
+
success: false,
|
|
4516
|
+
message: {
|
|
4517
|
+
text: await this.translateService.translateAsync('@general:messages.entity.invalid-data'),
|
|
4518
|
+
},
|
|
4519
|
+
};
|
|
4520
|
+
}
|
|
4521
|
+
if (findDuplicateOutcomeNames(outcomes).length > 0) {
|
|
4522
|
+
return {
|
|
4523
|
+
success: false,
|
|
4524
|
+
message: {
|
|
4525
|
+
text: await this.translateService.translateAsync('@assessment-management:questionnaires.components.questionnaire-outcomes-builder.validation.duplicate-name'),
|
|
4526
|
+
},
|
|
4527
|
+
};
|
|
4528
|
+
}
|
|
4529
|
+
const input = { id, outcomes };
|
|
4530
|
+
const result = await this.commandService.execute(QUESTIONNAIRE_OUTCOMES_SAVE_COMMAND, input);
|
|
4531
|
+
const execResult = (result ?? { success: false });
|
|
4532
|
+
if (execResult.success) {
|
|
4533
|
+
this.baselineOutcomes.set(this.cloneOutcomes(outcomes));
|
|
4534
|
+
this.localContext.set(null);
|
|
4535
|
+
this.isDirty.set(false);
|
|
4536
|
+
this.outcomesBaselinePendingReconcile.set(true);
|
|
4537
|
+
this.recompute();
|
|
4538
|
+
this.eventService.publish(AXPEntityEventsKeys.REFRESH_LAYOUT, {
|
|
4539
|
+
name: `${RootConfig.module.name}.${RootConfig.entities.questionnaire.name}`,
|
|
4540
|
+
});
|
|
4541
|
+
}
|
|
4542
|
+
return execResult;
|
|
4543
|
+
}
|
|
4544
|
+
//#endregion
|
|
4545
|
+
//#region ---- UI Handlers ----
|
|
4546
|
+
onOutcomesChange(value) {
|
|
4547
|
+
if (this.ignoreNextValueChange()) {
|
|
4548
|
+
this.ignoreNextValueChange.set(false);
|
|
4549
|
+
return;
|
|
4550
|
+
}
|
|
4551
|
+
const current = this.outcomesValue();
|
|
4552
|
+
if (this.areOutcomesEqual(current, value)) {
|
|
4553
|
+
if (this.outcomesBaselinePendingReconcile()) {
|
|
4554
|
+
this.baselineOutcomes.set(this.cloneOutcomes(current));
|
|
4555
|
+
this.outcomesBaselinePendingReconcile.set(false);
|
|
4556
|
+
this.isDirty.set(false);
|
|
4557
|
+
}
|
|
4558
|
+
return;
|
|
4559
|
+
}
|
|
4560
|
+
const base = this.localContext() ?? this.rootContext() ?? {};
|
|
4561
|
+
if (this.outcomesBaselinePendingReconcile() && this.localContext() == null) {
|
|
4562
|
+
this.baselineOutcomes.set(this.cloneOutcomes(value));
|
|
4563
|
+
this.isDirty.set(false);
|
|
4564
|
+
this.outcomesBaselinePendingReconcile.set(false);
|
|
4565
|
+
this.localContext.set({ ...base, outcomes: value });
|
|
4566
|
+
this.recompute();
|
|
4567
|
+
return;
|
|
4568
|
+
}
|
|
4569
|
+
this.localContext.set({ ...base, outcomes: value });
|
|
4570
|
+
const baseline = this.baselineOutcomes();
|
|
4571
|
+
this.isDirty.set(!this.areOutcomesEqual(baseline, value));
|
|
4572
|
+
this.recompute();
|
|
4573
|
+
}
|
|
4574
|
+
//#endregion
|
|
4575
|
+
//#region ---- Utility ----
|
|
4576
|
+
areOutcomesEqual(a, b) {
|
|
4577
|
+
return isEqual(normalizeQuestionnaireOutcomesValue(a), normalizeQuestionnaireOutcomesValue(b));
|
|
4578
|
+
}
|
|
4579
|
+
cloneOutcomes(value) {
|
|
4580
|
+
if (isNil(value)) {
|
|
4581
|
+
return { sections: [] };
|
|
4582
|
+
}
|
|
4583
|
+
return cloneDeep(normalizeQuestionnaireOutcomesValue(value));
|
|
4584
|
+
}
|
|
4585
|
+
recompute() {
|
|
4586
|
+
super.recompute();
|
|
4587
|
+
const maybeLayout = this.hostPageLayout;
|
|
4588
|
+
maybeLayout.recompute?.();
|
|
4589
|
+
}
|
|
4590
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMQuestionnaireOutcomesPageComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
4591
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "21.2.9", type: AXMQuestionnaireOutcomesPageComponent, isStandalone: true, selector: "axm-questionnaire-outcomes-page", inputs: { rootContext: { classPropertyName: "rootContext", publicName: "rootContext", isSignal: true, isRequired: false, transformFunction: null }, pageConfig: { classPropertyName: "pageConfig", publicName: "pageConfig", isSignal: true, isRequired: false, transformFunction: null } }, providers: [
|
|
4592
|
+
{
|
|
4593
|
+
provide: AXPPageLayoutBase,
|
|
4594
|
+
useExisting: AXMQuestionnaireOutcomesPageComponent,
|
|
4595
|
+
},
|
|
4596
|
+
], viewQueries: [{ propertyName: "builderRef", first: true, predicate: ["builderRef"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: `
|
|
4597
|
+
<axm-questionnaire-outcomes-builder
|
|
4598
|
+
#builderRef
|
|
4599
|
+
[value]="outcomesValue()"
|
|
4600
|
+
[showHeader]="false"
|
|
4601
|
+
(valueChange)="onOutcomesChange($event)">
|
|
4602
|
+
</axm-questionnaire-outcomes-builder>
|
|
4603
|
+
`, isInline: true, dependencies: [{ kind: "component", type: AXMQuestionnaireOutcomesBuilderComponent, selector: "axm-questionnaire-outcomes-builder", inputs: ["value", "readonly", "showHeader"], outputs: ["valueChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
4604
|
+
}
|
|
4605
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMQuestionnaireOutcomesPageComponent, decorators: [{
|
|
4606
|
+
type: Component,
|
|
1536
4607
|
args: [{
|
|
1537
|
-
|
|
4608
|
+
selector: 'axm-questionnaire-outcomes-page',
|
|
4609
|
+
standalone: true,
|
|
4610
|
+
imports: [AXMQuestionnaireOutcomesBuilderComponent],
|
|
4611
|
+
template: `
|
|
4612
|
+
<axm-questionnaire-outcomes-builder
|
|
4613
|
+
#builderRef
|
|
4614
|
+
[value]="outcomesValue()"
|
|
4615
|
+
[showHeader]="false"
|
|
4616
|
+
(valueChange)="onOutcomesChange($event)">
|
|
4617
|
+
</axm-questionnaire-outcomes-builder>
|
|
4618
|
+
`,
|
|
4619
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
4620
|
+
providers: [
|
|
4621
|
+
{
|
|
4622
|
+
provide: AXPPageLayoutBase,
|
|
4623
|
+
useExisting: AXMQuestionnaireOutcomesPageComponent,
|
|
4624
|
+
},
|
|
4625
|
+
],
|
|
1538
4626
|
}]
|
|
4627
|
+
}], ctorParameters: () => [], propDecorators: { rootContext: [{ type: i0.Input, args: [{ isSignal: true, alias: "rootContext", required: false }] }], pageConfig: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageConfig", required: false }] }], builderRef: [{ type: i0.ViewChild, args: ['builderRef', { isSignal: true }] }] } });
|
|
4628
|
+
|
|
4629
|
+
var questionnaireOutcomesPage_component = /*#__PURE__*/Object.freeze({
|
|
4630
|
+
__proto__: null,
|
|
4631
|
+
AXMQuestionnaireOutcomesPageComponent: AXMQuestionnaireOutcomesPageComponent
|
|
4632
|
+
});
|
|
4633
|
+
|
|
4634
|
+
//#region ---- Questionnaire Outcomes Page Component Provider ----
|
|
4635
|
+
class AXMQuestionnaireOutcomesPageComponentProvider {
|
|
4636
|
+
async components() {
|
|
4637
|
+
return [
|
|
4638
|
+
{
|
|
4639
|
+
key: QUESTIONNAIRE_OUTCOMES_PAGE_COMPONENT_KEY,
|
|
4640
|
+
loader: () => Promise.resolve().then(function () { return questionnaireOutcomesPage_component; }).then((m) => m.AXMQuestionnaireOutcomesPageComponent),
|
|
4641
|
+
},
|
|
4642
|
+
];
|
|
4643
|
+
}
|
|
4644
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMQuestionnaireOutcomesPageComponentProvider, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
4645
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMQuestionnaireOutcomesPageComponentProvider }); }
|
|
4646
|
+
}
|
|
4647
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMQuestionnaireOutcomesPageComponentProvider, decorators: [{
|
|
4648
|
+
type: Injectable
|
|
1539
4649
|
}] });
|
|
1540
4650
|
|
|
4651
|
+
var index = /*#__PURE__*/Object.freeze({
|
|
4652
|
+
__proto__: null,
|
|
4653
|
+
AXMQuestionnaireOutcomesPageComponent: AXMQuestionnaireOutcomesPageComponent,
|
|
4654
|
+
AXMQuestionnaireOutcomesPageComponentProvider: AXMQuestionnaireOutcomesPageComponentProvider,
|
|
4655
|
+
QUESTIONNAIRE_OUTCOMES_PAGE_COMPONENT_KEY: QUESTIONNAIRE_OUTCOMES_PAGE_COMPONENT_KEY
|
|
4656
|
+
});
|
|
4657
|
+
|
|
4658
|
+
//#region ---- Outcomes builder exports ----
|
|
4659
|
+
//#endregion
|
|
4660
|
+
|
|
4661
|
+
//#region ---- Questionnaire builder feature exports ----
|
|
4662
|
+
//#endregion
|
|
4663
|
+
|
|
1541
4664
|
//#region ---- Imports ----
|
|
1542
4665
|
//#endregion
|
|
1543
4666
|
/** Guards concurrent `refreshVisibility` runs; incremented on each refresh. */
|
|
@@ -1558,7 +4681,7 @@ function persistedItemName(item, index) {
|
|
|
1558
4681
|
const id = typeof legacy.id === 'string' ? legacy.id.trim() : '';
|
|
1559
4682
|
return id || `item-${index}`;
|
|
1560
4683
|
}
|
|
1561
|
-
function normalizeValidationStrategy
|
|
4684
|
+
function normalizeValidationStrategy(value) {
|
|
1562
4685
|
if (value === 'step' || value === 'end') {
|
|
1563
4686
|
return value;
|
|
1564
4687
|
}
|
|
@@ -1566,7 +4689,7 @@ function normalizeValidationStrategy$1(value) {
|
|
|
1566
4689
|
typeof value === 'object' &&
|
|
1567
4690
|
'id' in value &&
|
|
1568
4691
|
typeof value.id === 'string') {
|
|
1569
|
-
return normalizeValidationStrategy
|
|
4692
|
+
return normalizeValidationStrategy(value.id);
|
|
1570
4693
|
}
|
|
1571
4694
|
return 'step';
|
|
1572
4695
|
}
|
|
@@ -1963,8 +5086,8 @@ const AXMQuestionnaireViewerViewModel = signalStore(withState(() => ({
|
|
|
1963
5086
|
const displaySettings = structure?.displaySettings;
|
|
1964
5087
|
const displaySettingsValue = displaySettings?.validationStrategy;
|
|
1965
5088
|
return configValue !== undefined
|
|
1966
|
-
? normalizeValidationStrategy
|
|
1967
|
-
: normalizeValidationStrategy
|
|
5089
|
+
? normalizeValidationStrategy(configValue)
|
|
5090
|
+
: normalizeValidationStrategy(displaySettingsValue);
|
|
1968
5091
|
}),
|
|
1969
5092
|
//#endregion
|
|
1970
5093
|
//#region ---- Navigation ----
|
|
@@ -3483,7 +6606,7 @@ class AXMQuestionnaireViewerQuestionComponent {
|
|
|
3483
6606
|
</div>
|
|
3484
6607
|
}
|
|
3485
6608
|
</div>
|
|
3486
|
-
`, isInline: true, styles: ["axm-questionnaire-viewer-question{display:block}axm-questionnaire-viewer-question .__question-item{display:flex;flex-direction:column;gap:.25rem;padding:1rem;text-align:start;transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.2s;animation-duration:.2s}axm-questionnaire-viewer-question .__question-item.__answered{border-radius:.5rem;background:rgba(var(--ax-sys-color-primary-surface),.14)}axm-questionnaire-viewer-question .__question-item.__answered:not(.__view-mode){border-width:1px;--tw-border-opacity: 1;border-color:rgba(var(--ax-sys-color-border-surface),var(--tw-border-opacity, 1))}axm-questionnaire-viewer-question .__question-item .__question-header{display:flex;width:100%;min-width:0px;align-items:flex-start;justify-content:space-between;gap:1rem}axm-questionnaire-viewer-question .__question-item .__question-header .__question-header-left{display:flex;flex-shrink:0;align-items:center;gap:.75rem}axm-questionnaire-viewer-question .__question-item .__question-header .__question-header-left .__question-number{font-size:.875rem;line-height:1.25rem;font-weight:600;--tw-text-opacity: 1;color:rgba(var(--ax-sys-color-primary-600),var(--tw-text-opacity, 1))}axm-questionnaire-viewer-question .__question-item .__question-header .__question-header-left .__question-counter{font-size:.75rem;line-height:1rem;font-weight:500;color:rgb(var(--ax-sys-color-on-surface-variant))}axm-questionnaire-viewer-question .__question-item .__question-header .__question-header-right{display:flex;min-width:0px;flex:1 1 0%;flex-wrap:wrap;align-items:flex-start;gap:.5rem}axm-questionnaire-viewer-question .__question-item .__question-header .__question-header-right .__question-title-block{min-width:0px;flex:1 1 0%;text-align:start}axm-questionnaire-viewer-question .__question-item .__question-header .__question-header-right .__question-title-block .__question-title{margin:0;min-width:0px;flex:1 1 0%;text-align:start;font-size:1rem;line-height:1.5rem;color:rgb(var(--ax-sys-color-on-surface))}axm-questionnaire-viewer-question .__question-item .__question-header .__question-header-right .__question-title-block h3.__question-title{font-weight:500}axm-questionnaire-viewer-question .__question-item .__question-header .__question-header-right .__question-title-block .__question-title--rich{width:100%;max-width:100%;text-align:start;font-size:1rem;line-height:1.5rem;color:rgb(var(--ax-sys-color-on-surface))}axm-questionnaire-viewer-question .__question-item .__question-header .__question-header-right .__question-title-block .__question-title--rich p{margin:0}axm-questionnaire-viewer-question .__question-item .__question-header .__question-header-right .__question-title-block .__question-title--rich p:first-child{margin-top:0}axm-questionnaire-viewer-question .__question-item .__question-header .__question-header-right .__question-title-block .__question-title--rich ul{list-style-type:disc;list-style-position:outside;margin-block:.375rem 0;padding-inline-start:1.25rem}axm-questionnaire-viewer-question .__question-item .__question-header .__question-header-right .__question-title-block .__question-title--rich ol{list-style-type:decimal;list-style-position:outside;margin-block:.375rem 0;padding-inline-start:1.25rem}axm-questionnaire-viewer-question .__question-item .__question-header .__question-header-right .__question-title-block .__question-title--rich li{margin-block:.125rem;padding-inline-start:.25rem}axm-questionnaire-viewer-question .__question-item .__question-header .__question-header-right .__question-title-block .__question-title--rich ul ul{list-style-type:circle;margin-block:.25rem 0}axm-questionnaire-viewer-question .__question-item .__question-header .__question-header-right .__question-title-block .__question-title.__question-title--rich{font-weight:400}axm-questionnaire-viewer-question .__question-item .__question-header .__question-header-right .__answered-badge{border-radius:.25rem;padding:.25rem .5rem;font-size:.75rem;line-height:1rem;font-weight:500;background-color:rgb(var(--ax-sys-color-success-lighter-surface));color:rgb(var(--ax-sys-color-on-success-lighter-surface))}axm-questionnaire-viewer-question .__question-item .__question-header .__question-header-right .__required-badge{border-radius:.25rem;padding:.25rem .5rem;font-size:.75rem;line-height:1rem;font-weight:500;background-color:rgb(var(--ax-sys-color-warning-lighter-surface));color:rgb(var(--ax-sys-color-on-warning-lighter-surface))}axm-questionnaire-viewer-question .__question-item .__question-note{font-size:.875rem;line-height:1.25rem;color:rgb(var(--ax-sys-color-on-surface-variant))}axm-questionnaire-viewer-question .__question-item .__question-note p{margin:0}axm-questionnaire-viewer-question .__question-item .__question-note p:first-child{margin-top:0}axm-questionnaire-viewer-question .__question-item .__question-note ul{list-style-type:disc;list-style-position:outside;margin-block:.375rem 0;padding-inline-start:1.25rem}axm-questionnaire-viewer-question .__question-item .__question-note ol{list-style-type:decimal;list-style-position:outside;margin-block:.375rem 0;padding-inline-start:1.25rem}axm-questionnaire-viewer-question .__question-item .__question-note li{margin-block:.125rem}axm-questionnaire-viewer-question .__question-item .__question-description{margin-top:.25rem;font-size:.875rem;line-height:1.25rem;color:rgb(var(--ax-sys-color-on-surface-variant))}axm-questionnaire-viewer-question .__question-item .__question-widget{text-align:start}axm-questionnaire-viewer-question .__question-item .__question-widget>*{margin-bottom:0}axm-questionnaire-viewer-question .__question-item .__widget-placeholder{border-radius:.25rem;border-width:1px;border-style:dashed;padding:1rem;font-size:.875rem;line-height:1.25rem;font-style:italic;color:rgb(var(--ax-sys-color-on-surface-variant));--tw-border-opacity: 1;border-color:rgba(var(--ax-sys-color-border-surface),var(--tw-border-opacity, 1));background-color:rgb(var(--ax-sys-color-lighter-surface));color:rgb(var(--ax-sys-color-on-lighter-surface));border-color:rgb(var(--ax-sys-color-border-lighter-surface))}axm-questionnaire-viewer-question .__question-item .__question-comment{display:flex;width:100%;flex-direction:column;gap:.25rem}axm-questionnaire-viewer-question .__question-item .__question-comment ax-text-area{margin-top:.5rem}axm-questionnaire-viewer-question .__question-item .__question-comment--readonly{margin-top:.5rem}axm-questionnaire-viewer-question .__question-item .__question-comment-text{margin:0;width:100%;font-size:.875rem;line-height:1.25rem;white-space:pre-wrap;color:rgb(var(--ax-sys-color-on-surface))}axm-questionnaire-viewer-question .__question-item .__question-comment-label{font-size:.875rem;line-height:1.25rem;font-weight:500;color:rgb(var(--ax-sys-color-on-surface-variant))}axm-questionnaire-viewer-question .__question-item .__question-comment-required{color:rgb(var(--ax-sys-color-danger-600))}axm-questionnaire-viewer-question .__question-item .__attachments{border-top-width:1px;--tw-border-opacity: 1;border-color:rgba(var(--ax-sys-color-border-surface),var(--tw-border-opacity, 1));padding-top:.75rem}axm-questionnaire-viewer-question .__question-item .__attachments .__attachments-label{margin-inline-end:.5rem;font-size:.875rem;line-height:1.25rem;font-weight:500;color:rgb(var(--ax-sys-color-on-surface-variant))}axm-questionnaire-viewer-question .__question-item .__attachments .__attachments-list{margin:0;margin-top:.25rem;list-style-type:none;padding-left:0}axm-questionnaire-viewer-question .__question-item .__attachments .__attachments-list li{margin-top:.25rem}axm-questionnaire-viewer-question .__question-item .__attachments .__attachments-list li .__attachment-link{display:inline-flex;align-items:center;gap:.5rem;font-size:.875rem;line-height:1.25rem;text-decoration-line:underline;transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s;color:rgb(var(--ax-sys-color-primary-dark-surface))}axm-questionnaire-viewer-question .__question-item .__attachments .__attachments-list li .__attachment-link:hover{opacity:.9}axm-questionnaire-viewer-question .__question-item .__attachments .__attachments-list li .__attachment-link i{flex-shrink:0}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "ngmodule", type: AXPWidgetCoreModule }, { kind: "directive", type: i1.AXPWidgetRendererDirective, selector: "[axp-widget-renderer]", inputs: ["parentNode", "index", "mode", "node"], outputs: ["onOptionsChanged", "onValueChanged", "onLoad"], exportAs: ["widgetRenderer"] }, { kind: "ngmodule", type: AXAlertModule }, { kind: "component", type: i2.AXAlertComponent, selector: "ax-alert", inputs: ["color", "timeOut"], outputs: ["colorChange", "onClosed", "timeOutChange"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i2$1.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i2$1.AXDecoratorGenericComponent, selector: "ax-footer, ax-header, ax-content, ax-divider, ax-form-hint, ax-prefix, ax-suffix, ax-text, ax-title, ax-subtitle, ax-placeholder, ax-overlay" }, { kind: "ngmodule", type: AXTextAreaModule }, { kind: "component", type: i4.AXTextAreaComponent, selector: "ax-text-area", inputs: ["disabled", "tabIndex", "readonly", "value", "state", "name", "placeholder", "maxLength", "look", "rows", "allowResize", "showCounter", "class"], outputs: ["onBlur", "onFocus", "valueChange", "stateChange", "onValueChanged", "readonlyChange", "disabledChange", "onKeyDown", "onKeyUp", "onKeyPress"] }, { kind: "ngmodule", type: AXFormModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i5.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i5.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "pipe", type: i3.AsyncPipe, name: "async" }, { kind: "pipe", type: i4$1.AXTranslatorPipe, name: "translate" }, { kind: "pipe", type: AXSafePipe, name: "safe" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
|
|
6609
|
+
`, isInline: true, styles: ["axm-questionnaire-viewer-question{display:block}axm-questionnaire-viewer-question .__question-item{display:flex;flex-direction:column;gap:.25rem;padding:1rem;text-align:start;transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.2s;animation-duration:.2s}axm-questionnaire-viewer-question .__question-item.__answered{border-radius:.5rem;background:rgba(var(--ax-sys-color-primary-surface),.14)}axm-questionnaire-viewer-question .__question-item.__answered:not(.__view-mode){border-width:1px;--tw-border-opacity: 1;border-color:rgba(var(--ax-sys-color-border-surface),var(--tw-border-opacity, 1))}axm-questionnaire-viewer-question .__question-item .__question-header{display:flex;width:100%;min-width:0px;align-items:flex-start;justify-content:space-between;gap:1rem}axm-questionnaire-viewer-question .__question-item .__question-header .__question-header-left{display:flex;flex-shrink:0;align-items:center;gap:.75rem}axm-questionnaire-viewer-question .__question-item .__question-header .__question-header-left .__question-number{font-size:.875rem;line-height:1.25rem;font-weight:600;--tw-text-opacity: 1;color:rgba(var(--ax-sys-color-primary-600),var(--tw-text-opacity, 1))}axm-questionnaire-viewer-question .__question-item .__question-header .__question-header-left .__question-counter{font-size:.75rem;line-height:1rem;font-weight:500;color:rgb(var(--ax-sys-color-on-surface-variant))}axm-questionnaire-viewer-question .__question-item .__question-header .__question-header-right{display:flex;min-width:0px;flex:1 1 0%;flex-wrap:wrap;align-items:flex-start;gap:.5rem}axm-questionnaire-viewer-question .__question-item .__question-header .__question-header-right .__question-title-block{min-width:0px;flex:1 1 0%;text-align:start}axm-questionnaire-viewer-question .__question-item .__question-header .__question-header-right .__question-title-block .__question-title{margin:0;min-width:0px;flex:1 1 0%;text-align:start;font-size:1rem;line-height:1.5rem;color:rgb(var(--ax-sys-color-on-surface))}axm-questionnaire-viewer-question .__question-item .__question-header .__question-header-right .__question-title-block h3.__question-title{font-weight:500}axm-questionnaire-viewer-question .__question-item .__question-header .__question-header-right .__question-title-block .__question-title--rich{width:100%;max-width:100%;text-align:start;font-size:1rem;line-height:1.5rem;color:rgb(var(--ax-sys-color-on-surface))}axm-questionnaire-viewer-question .__question-item .__question-header .__question-header-right .__question-title-block .__question-title--rich p{margin:0}axm-questionnaire-viewer-question .__question-item .__question-header .__question-header-right .__question-title-block .__question-title--rich p:first-child{margin-top:0}axm-questionnaire-viewer-question .__question-item .__question-header .__question-header-right .__question-title-block .__question-title--rich ul{list-style-type:disc;list-style-position:outside;margin-block:.375rem 0;padding-inline-start:1.25rem}axm-questionnaire-viewer-question .__question-item .__question-header .__question-header-right .__question-title-block .__question-title--rich ol{list-style-type:decimal;list-style-position:outside;margin-block:.375rem 0;padding-inline-start:1.25rem}axm-questionnaire-viewer-question .__question-item .__question-header .__question-header-right .__question-title-block .__question-title--rich li{margin-block:.125rem;padding-inline-start:.25rem}axm-questionnaire-viewer-question .__question-item .__question-header .__question-header-right .__question-title-block .__question-title--rich ul ul{list-style-type:circle;margin-block:.25rem 0}axm-questionnaire-viewer-question .__question-item .__question-header .__question-header-right .__question-title-block .__question-title.__question-title--rich{font-weight:400}axm-questionnaire-viewer-question .__question-item .__question-header .__question-header-right .__answered-badge{border-radius:.25rem;padding:.25rem .5rem;font-size:.75rem;line-height:1rem;font-weight:500;background-color:rgb(var(--ax-sys-color-success-lighter-surface));color:rgb(var(--ax-sys-color-on-success-lighter-surface))}axm-questionnaire-viewer-question .__question-item .__question-header .__question-header-right .__required-badge{border-radius:.25rem;padding:.25rem .5rem;font-size:.75rem;line-height:1rem;font-weight:500;background-color:rgb(var(--ax-sys-color-warning-lighter-surface));color:rgb(var(--ax-sys-color-on-warning-lighter-surface))}axm-questionnaire-viewer-question .__question-item .__question-note{font-size:.875rem;line-height:1.25rem;color:rgb(var(--ax-sys-color-on-surface-variant))}axm-questionnaire-viewer-question .__question-item .__question-note p{margin:0}axm-questionnaire-viewer-question .__question-item .__question-note p:first-child{margin-top:0}axm-questionnaire-viewer-question .__question-item .__question-note ul{list-style-type:disc;list-style-position:outside;margin-block:.375rem 0;padding-inline-start:1.25rem}axm-questionnaire-viewer-question .__question-item .__question-note ol{list-style-type:decimal;list-style-position:outside;margin-block:.375rem 0;padding-inline-start:1.25rem}axm-questionnaire-viewer-question .__question-item .__question-note li{margin-block:.125rem}axm-questionnaire-viewer-question .__question-item .__question-description{margin-top:.25rem;font-size:.875rem;line-height:1.25rem;color:rgb(var(--ax-sys-color-on-surface-variant))}axm-questionnaire-viewer-question .__question-item .__question-widget{text-align:start}axm-questionnaire-viewer-question .__question-item .__question-widget>*{margin-bottom:0}axm-questionnaire-viewer-question .__question-item .__widget-placeholder{border-radius:.25rem;border-width:1px;border-style:dashed;padding:1rem;font-size:.875rem;line-height:1.25rem;font-style:italic;color:rgb(var(--ax-sys-color-on-surface-variant));--tw-border-opacity: 1;border-color:rgba(var(--ax-sys-color-border-surface),var(--tw-border-opacity, 1));background-color:rgb(var(--ax-sys-color-lighter-surface));color:rgb(var(--ax-sys-color-on-lighter-surface));border-color:rgb(var(--ax-sys-color-border-lighter-surface))}axm-questionnaire-viewer-question .__question-item .__question-comment{display:flex;width:100%;flex-direction:column;gap:.25rem}axm-questionnaire-viewer-question .__question-item .__question-comment ax-text-area{margin-top:.5rem}axm-questionnaire-viewer-question .__question-item .__question-comment--readonly{margin-top:.5rem}axm-questionnaire-viewer-question .__question-item .__question-comment-text{margin:0;width:100%;font-size:.875rem;line-height:1.25rem;white-space:pre-wrap;color:rgb(var(--ax-sys-color-on-surface))}axm-questionnaire-viewer-question .__question-item .__question-comment-label{font-size:.875rem;line-height:1.25rem;font-weight:500;color:rgb(var(--ax-sys-color-on-surface-variant))}axm-questionnaire-viewer-question .__question-item .__question-comment-required{color:rgb(var(--ax-sys-color-danger-600))}axm-questionnaire-viewer-question .__question-item .__attachments{border-top-width:1px;--tw-border-opacity: 1;border-color:rgba(var(--ax-sys-color-border-surface),var(--tw-border-opacity, 1));padding-top:.75rem}axm-questionnaire-viewer-question .__question-item .__attachments .__attachments-label{margin-inline-end:.5rem;font-size:.875rem;line-height:1.25rem;font-weight:500;color:rgb(var(--ax-sys-color-on-surface-variant))}axm-questionnaire-viewer-question .__question-item .__attachments .__attachments-list{margin:0;margin-top:.25rem;list-style-type:none;padding-left:0}axm-questionnaire-viewer-question .__question-item .__attachments .__attachments-list li{margin-top:.25rem}axm-questionnaire-viewer-question .__question-item .__attachments .__attachments-list li .__attachment-link{display:inline-flex;align-items:center;gap:.5rem;font-size:.875rem;line-height:1.25rem;text-decoration-line:underline;transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s;color:rgb(var(--ax-sys-color-primary-dark-surface))}axm-questionnaire-viewer-question .__question-item .__attachments .__attachments-list li .__attachment-link:hover{opacity:.9}axm-questionnaire-viewer-question .__question-item .__attachments .__attachments-list li .__attachment-link i{flex-shrink:0}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "ngmodule", type: AXPWidgetCoreModule }, { kind: "directive", type: i1$1.AXPWidgetRendererDirective, selector: "[axp-widget-renderer]", inputs: ["parentNode", "index", "mode", "node"], outputs: ["onOptionsChanged", "onValueChanged", "onLoad"], exportAs: ["widgetRenderer"] }, { kind: "ngmodule", type: AXAlertModule }, { kind: "component", type: i2$1.AXAlertComponent, selector: "ax-alert", inputs: ["color", "timeOut"], outputs: ["colorChange", "onClosed", "timeOutChange"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i2.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i2.AXDecoratorGenericComponent, selector: "ax-footer, ax-header, ax-content, ax-divider, ax-form-hint, ax-prefix, ax-suffix, ax-text, ax-title, ax-subtitle, ax-placeholder, ax-overlay" }, { kind: "ngmodule", type: AXTextAreaModule }, { kind: "component", type: i4$1.AXTextAreaComponent, selector: "ax-text-area", inputs: ["disabled", "tabIndex", "readonly", "value", "state", "name", "placeholder", "maxLength", "look", "rows", "allowResize", "showCounter", "class"], outputs: ["onBlur", "onFocus", "valueChange", "stateChange", "onValueChanged", "readonlyChange", "disabledChange", "onKeyDown", "onKeyUp", "onKeyPress"] }, { kind: "ngmodule", type: AXFormModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i5.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i5.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "pipe", type: i3.AsyncPipe, name: "async" }, { kind: "pipe", type: i4.AXTranslatorPipe, name: "translate" }, { kind: "pipe", type: AXSafePipe, name: "safe" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
|
|
3487
6610
|
}
|
|
3488
6611
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMQuestionnaireViewerQuestionComponent, decorators: [{
|
|
3489
6612
|
type: Component,
|
|
@@ -3685,7 +6808,7 @@ class AXMQuestionnaireViewerSectionHeaderComponent {
|
|
|
3685
6808
|
}
|
|
3686
6809
|
}
|
|
3687
6810
|
</div>
|
|
3688
|
-
`, isInline: true, styles: ["axm-questionnaire-viewer-section-header{display:block;color:rgb(var(--ax-sys-color-on-surface))}axm-questionnaire-viewer-section-header .__section-header{display:flex;flex-shrink:0;flex-direction:column;gap:.125rem;text-align:start}axm-questionnaire-viewer-section-header .__section-title-lg{margin:0;font-size:1.5rem;line-height:2rem;font-weight:600;color:rgb(var(--ax-sys-color-on-surface))}axm-questionnaire-viewer-section-header .__section-title-md{margin:0;font-size:1.25rem;line-height:1.75rem;font-weight:600;color:rgb(var(--ax-sys-color-on-surface))}axm-questionnaire-viewer-section-header .__section-description{margin:0;font-size:.875rem;line-height:1.25rem;color:rgb(var(--ax-sys-color-on-surface-variant))}axm-questionnaire-viewer-section-header .__section-description--rich{font-size:.875rem;line-height:1.25rem;color:rgb(var(--ax-sys-color-on-surface-variant))}axm-questionnaire-viewer-section-header .__section-description--rich p{margin:0}axm-questionnaire-viewer-section-header .__section-description--rich p:first-child{margin-top:0}axm-questionnaire-viewer-section-header .__section-description--rich ul{list-style-type:disc;list-style-position:outside;margin-block:.375rem 0;padding-inline-start:1.25rem}axm-questionnaire-viewer-section-header .__section-description--rich ol{list-style-type:decimal;list-style-position:outside;margin-block:.375rem 0;padding-inline-start:1.25rem}axm-questionnaire-viewer-section-header .__section-description--rich li{margin-block:.125rem;padding-inline-start:.25rem}axm-questionnaire-viewer-section-header .__mb-sm{margin-bottom:.5rem}axm-questionnaire-viewer-section-header .__mb-md{margin-bottom:1rem}\n"], dependencies: [{ kind: "ngmodule", type: AXTranslationModule }, { kind: "pipe", type: i4
|
|
6811
|
+
`, isInline: true, styles: ["axm-questionnaire-viewer-section-header{display:block;color:rgb(var(--ax-sys-color-on-surface))}axm-questionnaire-viewer-section-header .__section-header{display:flex;flex-shrink:0;flex-direction:column;gap:.125rem;text-align:start}axm-questionnaire-viewer-section-header .__section-title-lg{margin:0;font-size:1.5rem;line-height:2rem;font-weight:600;color:rgb(var(--ax-sys-color-on-surface))}axm-questionnaire-viewer-section-header .__section-title-md{margin:0;font-size:1.25rem;line-height:1.75rem;font-weight:600;color:rgb(var(--ax-sys-color-on-surface))}axm-questionnaire-viewer-section-header .__section-description{margin:0;font-size:.875rem;line-height:1.25rem;color:rgb(var(--ax-sys-color-on-surface-variant))}axm-questionnaire-viewer-section-header .__section-description--rich{font-size:.875rem;line-height:1.25rem;color:rgb(var(--ax-sys-color-on-surface-variant))}axm-questionnaire-viewer-section-header .__section-description--rich p{margin:0}axm-questionnaire-viewer-section-header .__section-description--rich p:first-child{margin-top:0}axm-questionnaire-viewer-section-header .__section-description--rich ul{list-style-type:disc;list-style-position:outside;margin-block:.375rem 0;padding-inline-start:1.25rem}axm-questionnaire-viewer-section-header .__section-description--rich ol{list-style-type:decimal;list-style-position:outside;margin-block:.375rem 0;padding-inline-start:1.25rem}axm-questionnaire-viewer-section-header .__section-description--rich li{margin-block:.125rem;padding-inline-start:.25rem}axm-questionnaire-viewer-section-header .__mb-sm{margin-bottom:.5rem}axm-questionnaire-viewer-section-header .__mb-md{margin-bottom:1rem}\n"], dependencies: [{ kind: "ngmodule", type: AXTranslationModule }, { kind: "pipe", type: i4.AXTranslatorPipe, name: "translate" }, { kind: "pipe", type: AXSafePipe, name: "safe" }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
|
|
3689
6812
|
}
|
|
3690
6813
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMQuestionnaireViewerSectionHeaderComponent, decorators: [{
|
|
3691
6814
|
type: Component,
|
|
@@ -3918,7 +7041,7 @@ class AXMQuestionnaireViewerSideMenuViewComponent {
|
|
|
3918
7041
|
return null;
|
|
3919
7042
|
}
|
|
3920
7043
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMQuestionnaireViewerSideMenuViewComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
3921
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: AXMQuestionnaireViewerSideMenuViewComponent, isStandalone: true, selector: "axm-questionnaire-viewer-side-menu-view", viewQueries: [{ propertyName: "tabRef", first: true, predicate: AXTabsComponent, descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"__side-menu-container\">\n <!-- Desktop Sidebar (Large screens) -->\n @if (deviceService.isLarge()) {\n <div class=\"__desktop-sidebar\" [axResizable]=\"true\">\n <ax-tabs class=\"__sidebar-tabs\" [look]=\"'with-line-color'\" [location]=\"'end'\" [fitParent]=\"true\">\n @for (sectionIndex of vm.sectionIndicesWithVisibleContent(); track sectionIndex) {\n <ax-tab-item\n [text]=\"(vm.sections()[sectionIndex].title | translate | async) || ''\"\n (onClick)=\"handleSectionClick(sectionIndex)\"\n [disabled]=\"isSectionDisabled(sectionIndex)\"\n >\n @if (getSectionBadgeCount(vm.sections()[sectionIndex].name) > 0) {\n <ax-badge\n [text]=\"getSectionBadgeCount(vm.sections()[sectionIndex].name).toString()\"\n [color]=\"'danger'\"\n >\n </ax-badge>\n }\n </ax-tab-item>\n }\n </ax-tabs>\n </div>\n }\n\n <!-- Mobile/Tablet: Drawer Container -->\n @if (deviceService.isSmall() || deviceService.isMedium()) {\n <ax-drawer-container class=\"__drawer-container\">\n <!-- Sidebar Drawer (Mobile) -->\n <ax-drawer\n #sidebarDrawer\n [location]=\"'start'\"\n [mode]=\"'overlay'\"\n [collapsed]=\"sidebarDrawerCollapsed()\"\n [closeOnBackdropClick]=\"true\"\n (onBackdropClick)=\"sidebarDrawerCollapsed.set(true)\"\n class=\"__sidebar-drawer ax-w-[250px]\"\n >\n <ax-content class=\"__sidebar-content\">\n <ax-tabs class=\"__sidebar-tabs\" [look]=\"'with-line-color'\" [location]=\"'end'\" [fitParent]=\"true\">\n @for (sectionIndex of vm.sectionIndicesWithVisibleContent(); track sectionIndex) {\n <ax-tab-item\n [text]=\"(vm.sections()[sectionIndex].title | translate | async) || ''\"\n (onClick)=\"handleSectionClick(sectionIndex)\"\n [active]=\"vm.currentSectionIndex() === sectionIndex\"\n [disabled]=\"isSectionDisabled(sectionIndex)\"\n >\n @if (getSectionBadgeCount(vm.sections()[sectionIndex].name) > 0) {\n <ax-badge\n [text]=\"getSectionBadgeCount(vm.sections()[sectionIndex].name).toString()\"\n [color]=\"'danger'\"\n >\n </ax-badge>\n }\n </ax-tab-item>\n }\n </ax-tabs>\n </ax-content>\n </ax-drawer>\n\n <!-- Main Content (Mobile) -->\n <ax-content class=\"__main-content\">\n <!-- Questions Content -->\n @if (vm.currentSection(); as section) {\n @if (vm.isSectionVisible(section)) {\n @if (stickyParent(); as parent) {\n <div class=\"__mobile-header-row\" [axpSticky]=\"'--stuck'\" [stickyParent]=\"parent\" [stickyOffset]=\"0\">\n <div class=\"__mobile-menu-button\">\n <ax-button look=\"blank\" (onClick)=\"sidebarDrawerCollapsed.set(!sidebarDrawerCollapsed())\">\n <ax-prefix>\n <ax-icon icon=\"fa-light fa-bars\"></ax-icon>\n </ax-prefix>\n </ax-button>\n </div>\n\n <axm-questionnaire-viewer-section-header\n [title]=\"section.title\"\n [description]=\"section.description\"\n [titleSize]=\"'lg'\"\n [marginBottom]=\"'none'\"\n >\n </axm-questionnaire-viewer-section-header>\n </div>\n }\n\n <div class=\"__page-section\">\n <div class=\"__questions-list\">\n @for (question of vm.getVisibleQuestionsInSection(section); track question.name; let i = $index) {\n <axm-questionnaire-viewer-question\n [question]=\"question\"\n [sectionOrder]=\"section.order\"\n [questionIndex]=\"i + 1\"\n [showQuestionNumbers]=\"vm.showQuestionNumbers()\"\n [showQuestionCounter]=\"false\"\n >\n </axm-questionnaire-viewer-question>\n }\n </div>\n </div>\n }\n }\n </ax-content>\n </ax-drawer-container>\n } @else {\n <!-- Desktop Main Content -->\n <div class=\"__main-content\">\n <!-- Questions Content -->\n @if (vm.currentSection(); as section) {\n @if (vm.isSectionVisible(section)) {\n <div class=\"__page-section\">\n @if (stickyParent(); as parent) {\n <div\n class=\"__section-title-sticky\"\n [axpSticky]=\"'--stuck'\"\n [stickyParent]=\"parent\"\n [stickyOffset]=\"0\"\n >\n <axm-questionnaire-viewer-section-header\n [title]=\"section.title\"\n [description]=\"section.description\"\n [titleSize]=\"'lg'\"\n [marginBottom]=\"'none'\"\n >\n </axm-questionnaire-viewer-section-header>\n </div>\n }\n\n <div class=\"__questions-list\">\n @for (question of vm.getVisibleQuestionsInSection(section); track question.name; let i = $index) {\n <axm-questionnaire-viewer-question\n [question]=\"question\"\n [sectionOrder]=\"section.order\"\n [questionIndex]=\"i + 1\"\n [showQuestionNumbers]=\"vm.showQuestionNumbers()\"\n [showQuestionCounter]=\"false\"\n >\n </axm-questionnaire-viewer-question>\n }\n </div>\n </div>\n }\n }\n </div>\n }\n</div>\n", styles: ["axm-questionnaire-viewer-side-menu-view{display:block;min-height:0px;width:100%;overflow:hidden}@media(min-width:640px){axm-questionnaire-viewer-side-menu-view{height:100%}}@media(min-width:1024px){axm-questionnaire-viewer-side-menu-view{height:65vh}}.__side-menu-container{display:flex;height:100%;min-height:0px;width:100%;overflow:hidden}.__drawer-container{display:flex;height:100%;width:100%;overflow:hidden}.__sidebar-drawer{height:100%;border-inline-end-width:1px;--tw-border-opacity: 1;border-color:rgba(var(--ax-sys-color-border-surface),var(--tw-border-opacity, 1));background-color:rgb(var(--ax-sys-color-lightest-surface));color:rgb(var(--ax-sys-color-on-lightest-surface));border-color:rgb(var(--ax-sys-color-border-lightest-surface))}.__sidebar-content{height:100%;overflow-y:auto}.__desktop-sidebar{display:flex;height:100%;min-height:0px;flex-shrink:0;flex-direction:column;overflow:hidden;border-inline-end-width:1px;--tw-border-opacity: 1;border-color:rgba(var(--ax-sys-color-border-surface),var(--tw-border-opacity, 1));background-color:rgb(var(--ax-sys-color-lightest-surface));color:rgb(var(--ax-sys-color-on-lightest-surface));border-color:rgb(var(--ax-sys-color-border-lightest-surface))}.__sidebar-tabs{--ax-comp-tabs-default-border-radius: 0;height:100%;min-height:0px;flex:1 1 0%;overflow-y:auto}.__sidebar-tabs ax-tab-item{margin-top:0;margin-bottom:0;padding-top:.75rem;padding-bottom:.75rem;font-weight:600}.__main-content{display:flex;max-height:83vh;min-height:0px;flex:1 1 0%;flex-direction:column;overflow-y:auto}@media(min-width:768px){.__main-content{max-height:75vh}}.__page-section{display:flex;flex-shrink:0;flex-direction:column;gap:1rem;padding:1rem}.__page-section .__section-title-sticky{position:sticky;top:0;z-index:10;isolation:isolate;min-width:0px;align-self:stretch;border-bottom-width:1px;padding-top:.5rem;padding-bottom:.5rem;transition:padding-block .28s cubic-bezier(.33,1,.68,1),border-color .22s ease-out}.__page-section .__section-title-sticky:before{content:\"\";position:absolute;z-index:-1;inset-block:0;inset-inline:0;pointer-events:none;box-shadow:none;transition:inset-inline .28s cubic-bezier(.22,1,.36,1),box-shadow .28s cubic-bezier(.33,1,.68,1)}@media(prefers-reduced-motion:reduce){.__page-section .__section-title-sticky{transition-duration:1ms;transition-timing-function:linear}.__page-section .__section-title-sticky:before{transition-duration:1ms;transition-timing-function:linear}}.__page-section .__section-title-sticky.--stuck{border-bottom-width:1px;border-style:none;padding-top:.75rem;padding-bottom:.75rem;background-color:rgb(var(--ax-sys-color-lightest-surface));color:rgb(var(--ax-sys-color-on-lightest-surface));border-color:rgb(var(--ax-sys-color-border-lightest-surface))}.__page-section .__section-title-sticky.--stuck:before{inset-inline:-1rem;--tw-shadow: 0 4px 6px -1px rgb(0 0 0 / .1), 0 2px 4px -2px rgb(0 0 0 / .1);--tw-shadow-colored: 0 4px 6px -1px var(--tw-shadow-color), 0 2px 4px -2px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.__mobile-header-row{position:sticky;top:0;z-index:10;isolation:isolate;display:flex;flex-shrink:0;align-items:flex-start;gap:.5rem;border-bottom-width:1px;padding:.5rem 1rem;transition:padding-block .28s cubic-bezier(.33,1,.68,1),border-color .22s ease-out}.__mobile-header-row:before{content:\"\";position:absolute;z-index:-1;inset-block:0;inset-inline:0;pointer-events:none;box-shadow:none;transition:inset-inline .28s cubic-bezier(.22,1,.36,1),box-shadow .28s cubic-bezier(.33,1,.68,1)}.__mobile-header-row.--stuck{border-bottom-width:1px;border-style:none;padding-top:.75rem;padding-bottom:.75rem;background-color:rgb(var(--ax-sys-color-lightest-surface));color:rgb(var(--ax-sys-color-on-lightest-surface));border-color:rgb(var(--ax-sys-color-border-lightest-surface))}.__mobile-header-row.--stuck:before{inset-inline:-1rem;--tw-shadow: 0 4px 6px -1px rgb(0 0 0 / .1), 0 2px 4px -2px rgb(0 0 0 / .1);--tw-shadow-colored: 0 4px 6px -1px var(--tw-shadow-color), 0 2px 4px -2px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.__mobile-menu-button{margin-inline-start:-.5rem;flex-shrink:0}.__questions-list{display:flex;flex-direction:column;gap:1rem}\n"], dependencies: [{ kind: "component", type: AXMQuestionnaireViewerQuestionComponent, selector: "axm-questionnaire-viewer-question", inputs: ["question", "contextData", "sectionOrder", "questionIndex", "showQuestionNumbers", "showQuestionCounter", "currentPosition", "mode"] }, { kind: "component", type: AXMQuestionnaireViewerSectionHeaderComponent, selector: "axm-questionnaire-viewer-section-header", inputs: ["title", "description", "titleSize", "marginBottom"] }, { kind: "ngmodule", type: AXTabsModule }, { kind: "component", type: i1$1.AXTabsComponent, selector: "ax-tabs", inputs: ["look", "location", "fitParent", "minWidth", "content"], outputs: ["onActiveTabChanged"] }, { kind: "component", type: i1$1.AXTabItemComponent, selector: "ax-tab-item", inputs: ["disabled", "text", "key", "headerTemplate", "active"], outputs: ["disabledChange", "onClick", "onBlur", "onFocus", "activeChange"] }, { kind: "ngmodule", type: AXBadgeModule }, { kind: "component", type: i2$2.AXBadgeComponent, selector: "ax-badge", inputs: ["color", "look", "text"] }, { kind: "ngmodule", type: AXDrawerModule }, { kind: "component", type: i3$1.AXDrawerComponent, selector: "ax-drawer", inputs: ["location", "showBackdrop", "mode", "transition", "closeOnBackdropClick", "backdropClass", "collapsed", "singleOpenMode"], outputs: ["onBackdropClick", "collapsedStateChanged"] }, { kind: "component", type: i3$1.AXDrawerContainerComponent, selector: "ax-drawer-container" }, { kind: "ngmodule", type: AXDrawerDirectiveModule }, { kind: "directive", type: AXResizableDirective, selector: "[axResizable]", inputs: ["axResizable", "minWidth", "maxWidth", "dblClickAction", "width", "defaultWidth"], outputs: ["axResizableChange", "minWidthChange", "maxWidthChange", "dblClickActionChange", "widthChange", "defaultWidthChange", "onResizingStarted", "onResizingEnded", "onResizingDblClick"] }, { kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i1$2.AXButtonComponent, selector: "ax-button", inputs: ["disabled", "size", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i2$1.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i2$1.AXDecoratorGenericComponent, selector: "ax-footer, ax-header, ax-content, ax-divider, ax-form-hint, ax-prefix, ax-suffix, ax-text, ax-title, ax-subtitle, ax-placeholder, ax-overlay" }, { kind: "directive", type: AXPStickyDirective, selector: "[axpSticky]", inputs: ["axpSticky", "stickyOffset", "stickyParent", "stickyTarget"], outputs: ["isStickyChange"], exportAs: ["axpSticky"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "pipe", type: i4$1.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
|
|
7044
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: AXMQuestionnaireViewerSideMenuViewComponent, isStandalone: true, selector: "axm-questionnaire-viewer-side-menu-view", viewQueries: [{ propertyName: "tabRef", first: true, predicate: AXTabsComponent, descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"__side-menu-container\">\n <!-- Desktop Sidebar (Large screens) -->\n @if (deviceService.isLarge()) {\n <div class=\"__desktop-sidebar\" [axResizable]=\"true\">\n <ax-tabs class=\"__sidebar-tabs\" [look]=\"'with-line-color'\" [location]=\"'end'\" [fitParent]=\"true\">\n @for (sectionIndex of vm.sectionIndicesWithVisibleContent(); track sectionIndex) {\n <ax-tab-item\n [text]=\"(vm.sections()[sectionIndex].title | translate | async) || ''\"\n (onClick)=\"handleSectionClick(sectionIndex)\"\n [disabled]=\"isSectionDisabled(sectionIndex)\"\n >\n @if (getSectionBadgeCount(vm.sections()[sectionIndex].name) > 0) {\n <ax-badge\n [text]=\"getSectionBadgeCount(vm.sections()[sectionIndex].name).toString()\"\n [color]=\"'danger'\"\n >\n </ax-badge>\n }\n </ax-tab-item>\n }\n </ax-tabs>\n </div>\n }\n\n <!-- Mobile/Tablet: Drawer Container -->\n @if (deviceService.isSmall() || deviceService.isMedium()) {\n <ax-drawer-container class=\"__drawer-container\">\n <!-- Sidebar Drawer (Mobile) -->\n <ax-drawer\n #sidebarDrawer\n [location]=\"'start'\"\n [mode]=\"'overlay'\"\n [collapsed]=\"sidebarDrawerCollapsed()\"\n [closeOnBackdropClick]=\"true\"\n (onBackdropClick)=\"sidebarDrawerCollapsed.set(true)\"\n class=\"__sidebar-drawer ax-w-[250px]\"\n >\n <ax-content class=\"__sidebar-content\">\n <ax-tabs class=\"__sidebar-tabs\" [look]=\"'with-line-color'\" [location]=\"'end'\" [fitParent]=\"true\">\n @for (sectionIndex of vm.sectionIndicesWithVisibleContent(); track sectionIndex) {\n <ax-tab-item\n [text]=\"(vm.sections()[sectionIndex].title | translate | async) || ''\"\n (onClick)=\"handleSectionClick(sectionIndex)\"\n [active]=\"vm.currentSectionIndex() === sectionIndex\"\n [disabled]=\"isSectionDisabled(sectionIndex)\"\n >\n @if (getSectionBadgeCount(vm.sections()[sectionIndex].name) > 0) {\n <ax-badge\n [text]=\"getSectionBadgeCount(vm.sections()[sectionIndex].name).toString()\"\n [color]=\"'danger'\"\n >\n </ax-badge>\n }\n </ax-tab-item>\n }\n </ax-tabs>\n </ax-content>\n </ax-drawer>\n\n <!-- Main Content (Mobile) -->\n <ax-content class=\"__main-content\">\n <!-- Questions Content -->\n @if (vm.currentSection(); as section) {\n @if (vm.isSectionVisible(section)) {\n @if (stickyParent(); as parent) {\n <div class=\"__mobile-header-row\" [axpSticky]=\"'--stuck'\" [stickyParent]=\"parent\" [stickyOffset]=\"0\">\n <div class=\"__mobile-menu-button\">\n <ax-button look=\"blank\" (onClick)=\"sidebarDrawerCollapsed.set(!sidebarDrawerCollapsed())\">\n <ax-prefix>\n <ax-icon icon=\"fa-light fa-bars\"></ax-icon>\n </ax-prefix>\n </ax-button>\n </div>\n\n <axm-questionnaire-viewer-section-header\n [title]=\"section.title\"\n [description]=\"section.description\"\n [titleSize]=\"'lg'\"\n [marginBottom]=\"'none'\"\n >\n </axm-questionnaire-viewer-section-header>\n </div>\n }\n\n <div class=\"__page-section\">\n <div class=\"__questions-list\">\n @for (question of vm.getVisibleQuestionsInSection(section); track question.name; let i = $index) {\n <axm-questionnaire-viewer-question\n [question]=\"question\"\n [sectionOrder]=\"section.order\"\n [questionIndex]=\"i + 1\"\n [showQuestionNumbers]=\"vm.showQuestionNumbers()\"\n [showQuestionCounter]=\"false\"\n >\n </axm-questionnaire-viewer-question>\n }\n </div>\n </div>\n }\n }\n </ax-content>\n </ax-drawer-container>\n } @else {\n <!-- Desktop Main Content -->\n <div class=\"__main-content\">\n <!-- Questions Content -->\n @if (vm.currentSection(); as section) {\n @if (vm.isSectionVisible(section)) {\n <div class=\"__page-section\">\n @if (stickyParent(); as parent) {\n <div\n class=\"__section-title-sticky\"\n [axpSticky]=\"'--stuck'\"\n [stickyParent]=\"parent\"\n [stickyOffset]=\"0\"\n >\n <axm-questionnaire-viewer-section-header\n [title]=\"section.title\"\n [description]=\"section.description\"\n [titleSize]=\"'lg'\"\n [marginBottom]=\"'none'\"\n >\n </axm-questionnaire-viewer-section-header>\n </div>\n }\n\n <div class=\"__questions-list\">\n @for (question of vm.getVisibleQuestionsInSection(section); track question.name; let i = $index) {\n <axm-questionnaire-viewer-question\n [question]=\"question\"\n [sectionOrder]=\"section.order\"\n [questionIndex]=\"i + 1\"\n [showQuestionNumbers]=\"vm.showQuestionNumbers()\"\n [showQuestionCounter]=\"false\"\n >\n </axm-questionnaire-viewer-question>\n }\n </div>\n </div>\n }\n }\n </div>\n }\n</div>\n", styles: ["axm-questionnaire-viewer-side-menu-view{display:block;min-height:0px;width:100%;overflow:hidden}@media(min-width:640px){axm-questionnaire-viewer-side-menu-view{height:100%}}@media(min-width:1024px){axm-questionnaire-viewer-side-menu-view{height:65vh}}.__side-menu-container{display:flex;height:100%;min-height:0px;width:100%;overflow:hidden}.__drawer-container{display:flex;height:100%;width:100%;overflow:hidden}.__sidebar-drawer{height:100%;border-inline-end-width:1px;--tw-border-opacity: 1;border-color:rgba(var(--ax-sys-color-border-surface),var(--tw-border-opacity, 1));background-color:rgb(var(--ax-sys-color-lightest-surface));color:rgb(var(--ax-sys-color-on-lightest-surface));border-color:rgb(var(--ax-sys-color-border-lightest-surface))}.__sidebar-content{height:100%;overflow-y:auto}.__desktop-sidebar{display:flex;height:100%;min-height:0px;flex-shrink:0;flex-direction:column;overflow:hidden;border-inline-end-width:1px;--tw-border-opacity: 1;border-color:rgba(var(--ax-sys-color-border-surface),var(--tw-border-opacity, 1));background-color:rgb(var(--ax-sys-color-lightest-surface));color:rgb(var(--ax-sys-color-on-lightest-surface));border-color:rgb(var(--ax-sys-color-border-lightest-surface))}.__sidebar-tabs{--ax-comp-tabs-default-border-radius: 0;height:100%;min-height:0px;flex:1 1 0%;overflow-y:auto}.__sidebar-tabs ax-tab-item{margin-top:0;margin-bottom:0;padding-top:.75rem;padding-bottom:.75rem;font-weight:600}.__main-content{display:flex;max-height:83vh;min-height:0px;flex:1 1 0%;flex-direction:column;overflow-y:auto}@media(min-width:768px){.__main-content{max-height:75vh}}.__page-section{display:flex;flex-shrink:0;flex-direction:column;gap:1rem;padding:1rem}.__page-section .__section-title-sticky{position:sticky;top:0;z-index:10;isolation:isolate;min-width:0px;align-self:stretch;border-bottom-width:1px;padding-top:.5rem;padding-bottom:.5rem;transition:padding-block .28s cubic-bezier(.33,1,.68,1),border-color .22s ease-out}.__page-section .__section-title-sticky:before{content:\"\";position:absolute;z-index:-1;inset-block:0;inset-inline:0;pointer-events:none;box-shadow:none;transition:inset-inline .28s cubic-bezier(.22,1,.36,1),box-shadow .28s cubic-bezier(.33,1,.68,1)}@media(prefers-reduced-motion:reduce){.__page-section .__section-title-sticky{transition-duration:1ms;transition-timing-function:linear}.__page-section .__section-title-sticky:before{transition-duration:1ms;transition-timing-function:linear}}.__page-section .__section-title-sticky.--stuck{border-bottom-width:1px;border-style:none;padding-top:.75rem;padding-bottom:.75rem;background-color:rgb(var(--ax-sys-color-lightest-surface));color:rgb(var(--ax-sys-color-on-lightest-surface));border-color:rgb(var(--ax-sys-color-border-lightest-surface))}.__page-section .__section-title-sticky.--stuck:before{inset-inline:-1rem;--tw-shadow: 0 4px 6px -1px rgb(0 0 0 / .1), 0 2px 4px -2px rgb(0 0 0 / .1);--tw-shadow-colored: 0 4px 6px -1px var(--tw-shadow-color), 0 2px 4px -2px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.__mobile-header-row{position:sticky;top:0;z-index:10;isolation:isolate;display:flex;flex-shrink:0;align-items:flex-start;gap:.5rem;border-bottom-width:1px;padding:.5rem 1rem;transition:padding-block .28s cubic-bezier(.33,1,.68,1),border-color .22s ease-out}.__mobile-header-row:before{content:\"\";position:absolute;z-index:-1;inset-block:0;inset-inline:0;pointer-events:none;box-shadow:none;transition:inset-inline .28s cubic-bezier(.22,1,.36,1),box-shadow .28s cubic-bezier(.33,1,.68,1)}.__mobile-header-row.--stuck{border-bottom-width:1px;border-style:none;padding-top:.75rem;padding-bottom:.75rem;background-color:rgb(var(--ax-sys-color-lightest-surface));color:rgb(var(--ax-sys-color-on-lightest-surface));border-color:rgb(var(--ax-sys-color-border-lightest-surface))}.__mobile-header-row.--stuck:before{inset-inline:-1rem;--tw-shadow: 0 4px 6px -1px rgb(0 0 0 / .1), 0 2px 4px -2px rgb(0 0 0 / .1);--tw-shadow-colored: 0 4px 6px -1px var(--tw-shadow-color), 0 2px 4px -2px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.__mobile-menu-button{margin-inline-start:-.5rem;flex-shrink:0}.__questions-list{display:flex;flex-direction:column;gap:1rem}\n"], dependencies: [{ kind: "component", type: AXMQuestionnaireViewerQuestionComponent, selector: "axm-questionnaire-viewer-question", inputs: ["question", "contextData", "sectionOrder", "questionIndex", "showQuestionNumbers", "showQuestionCounter", "currentPosition", "mode"] }, { kind: "component", type: AXMQuestionnaireViewerSectionHeaderComponent, selector: "axm-questionnaire-viewer-section-header", inputs: ["title", "description", "titleSize", "marginBottom"] }, { kind: "ngmodule", type: AXTabsModule }, { kind: "component", type: i1$2.AXTabsComponent, selector: "ax-tabs", inputs: ["look", "location", "fitParent", "minWidth", "content"], outputs: ["onActiveTabChanged"] }, { kind: "component", type: i1$2.AXTabItemComponent, selector: "ax-tab-item", inputs: ["disabled", "text", "key", "headerTemplate", "active"], outputs: ["disabledChange", "onClick", "onBlur", "onFocus", "activeChange"] }, { kind: "ngmodule", type: AXBadgeModule }, { kind: "component", type: i2$2.AXBadgeComponent, selector: "ax-badge", inputs: ["color", "look", "text"] }, { kind: "ngmodule", type: AXDrawerModule }, { kind: "component", type: i3$1.AXDrawerComponent, selector: "ax-drawer", inputs: ["location", "showBackdrop", "mode", "transition", "closeOnBackdropClick", "backdropClass", "collapsed", "singleOpenMode"], outputs: ["onBackdropClick", "collapsedStateChanged"] }, { kind: "component", type: i3$1.AXDrawerContainerComponent, selector: "ax-drawer-container" }, { kind: "ngmodule", type: AXDrawerDirectiveModule }, { kind: "directive", type: AXResizableDirective, selector: "[axResizable]", inputs: ["axResizable", "minWidth", "maxWidth", "dblClickAction", "width", "defaultWidth"], outputs: ["axResizableChange", "minWidthChange", "maxWidthChange", "dblClickActionChange", "widthChange", "defaultWidthChange", "onResizingStarted", "onResizingEnded", "onResizingDblClick"] }, { kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i1.AXButtonComponent, selector: "ax-button", inputs: ["disabled", "size", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i2.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i2.AXDecoratorGenericComponent, selector: "ax-footer, ax-header, ax-content, ax-divider, ax-form-hint, ax-prefix, ax-suffix, ax-text, ax-title, ax-subtitle, ax-placeholder, ax-overlay" }, { kind: "directive", type: AXPStickyDirective, selector: "[axpSticky]", inputs: ["axpSticky", "stickyOffset", "stickyParent", "stickyTarget"], outputs: ["isStickyChange"], exportAs: ["axpSticky"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "pipe", type: i4.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
|
|
3922
7045
|
}
|
|
3923
7046
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMQuestionnaireViewerSideMenuViewComponent, decorators: [{
|
|
3924
7047
|
type: Component,
|
|
@@ -4183,9 +7306,9 @@ class AXMQuestionnaireViewerComponent {
|
|
|
4183
7306
|
this.answersChanged.emit(answers);
|
|
4184
7307
|
}
|
|
4185
7308
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMQuestionnaireViewerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
4186
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: AXMQuestionnaireViewerComponent, isStandalone: true, selector: "axm-questionnaire-viewer", inputs: { questionnaireId: { classPropertyName: "questionnaireId", publicName: "questionnaireId", isSignal: true, isRequired: false, transformFunction: null }, structure: { classPropertyName: "structure", publicName: "structure", isSignal: true, isRequired: false, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null }, initialAnswers: { classPropertyName: "initialAnswers", publicName: "initialAnswers", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { answersChanged: "answersChanged", questionAnswered: "questionAnswered" }, host: { classAttribute: "axm-questionnaire-viewer" }, providers: [AXMQuestionnaireViewerViewModel], viewQueries: [{ propertyName: "form", first: true, predicate: ["form"], descendants: true, isSignal: true }, { propertyName: "widgetContainer", first: true, predicate: AXPWidgetContainerComponent, descendants: true, isSignal: true }], ngImport: i0, template: "<axp-widgets-container #widgetContainer [attr.dir]=\"layoutDirection()\" [context]=\"{}\"\n (onContextChanged)=\"handleContextChanged()\">\n @if (vm.isLoading()) {\n <div class=\"__loading\">\n <axp-state-message icon=\"fa-light fa-spinner fa-spin\"\n [title]=\"('@assessment-management:questionnaires.components.questionnaire-viewer.loading.title' | translate | async) || ''\"\n [description]=\"('@assessment-management:questionnaires.components.questionnaire-viewer.loading.description' | translate | async) || ''\">\n </axp-state-message>\n </div>\n } @else if (vm.error()) {\n <div class=\"__error\">\n <axp-state-message icon=\"fa-light fa-exclamation-triangle\"\n [title]=\"('@assessment-management:questionnaires.components.questionnaire-viewer.error.title' | translate | async) || ''\"\n [description]=\"vm.error() || ''\">\n </axp-state-message>\n </div>\n } @else if (vm.questionnaireData()) {\n <div class=\"__questionnaire-container\">\n <ax-form #form>\n @if (vm.viewMode() === 'single-page') {\n <axm-questionnaire-viewer-single-page-view></axm-questionnaire-viewer-single-page-view>\n } @else if (vm.viewMode() === 'page-per-group') {\n <axm-questionnaire-viewer-page-per-group-view></axm-questionnaire-viewer-page-per-group-view>\n } @else if (vm.viewMode() === 'page-per-question') {\n <axm-questionnaire-viewer-page-per-question-view></axm-questionnaire-viewer-page-per-question-view>\n } @else if (vm.viewMode() === 'side-menu') {\n <axm-questionnaire-viewer-side-menu-view></axm-questionnaire-viewer-side-menu-view>\n }\n </ax-form>\n </div>\n }\n</axp-widgets-container>\n", styles: [".axm-questionnaire-viewer{display:flex;height:100%;max-height:100%;min-height:0px;width:100%;flex:1 1 0%;flex-direction:column}.axm-questionnaire-viewer ax-form{display:flex;height:100%;min-height:0px;flex:1 1 0%;flex-direction:column}.axm-questionnaire-viewer axp-widgets-container{display:flex;height:100%;min-height:0px;flex:1 1 0%;flex-direction:column}.axm-questionnaire-viewer .__loading,.axm-questionnaire-viewer .__error{display:flex;height:100%;align-items:center;justify-content:center}.axm-questionnaire-viewer .__questionnaire-container{display:flex;min-height:0px;flex:1 1 0%;flex-direction:column;overflow:hidden}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "component", type: AXPStateMessageComponent, selector: "axp-state-message", inputs: ["mode", "icon", "title", "description", "look"] }, { kind: "ngmodule", type: AXFormModule }, { kind: "component", type: i1$3.AXFormComponent, selector: "ax-form", inputs: ["disabled", "readonly", "labelMode", "look", "messageStyle", "updateOn", "inUserInteractionActive"], outputs: ["onValidate", "updateOnChange"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "ngmodule", type: AXPWidgetCoreModule }, { kind: "component", type: i1.AXPWidgetContainerComponent, selector: "axp-widgets-container", inputs: ["context", "functions"], outputs: ["onContextChanged"] }, { kind: "component", type:
|
|
7309
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: AXMQuestionnaireViewerComponent, isStandalone: true, selector: "axm-questionnaire-viewer", inputs: { questionnaireId: { classPropertyName: "questionnaireId", publicName: "questionnaireId", isSignal: true, isRequired: false, transformFunction: null }, structure: { classPropertyName: "structure", publicName: "structure", isSignal: true, isRequired: false, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null }, initialAnswers: { classPropertyName: "initialAnswers", publicName: "initialAnswers", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { answersChanged: "answersChanged", questionAnswered: "questionAnswered" }, host: { classAttribute: "axm-questionnaire-viewer" }, providers: [AXMQuestionnaireViewerViewModel], viewQueries: [{ propertyName: "form", first: true, predicate: ["form"], descendants: true, isSignal: true }, { propertyName: "widgetContainer", first: true, predicate: AXPWidgetContainerComponent, descendants: true, isSignal: true }], ngImport: i0, template: "<axp-widgets-container #widgetContainer [attr.dir]=\"layoutDirection()\" [context]=\"{}\"\n (onContextChanged)=\"handleContextChanged()\">\n @if (vm.isLoading()) {\n <div class=\"__loading\">\n <axp-state-message icon=\"fa-light fa-spinner fa-spin\"\n [title]=\"('@assessment-management:questionnaires.components.questionnaire-viewer.loading.title' | translate | async) || ''\"\n [description]=\"('@assessment-management:questionnaires.components.questionnaire-viewer.loading.description' | translate | async) || ''\">\n </axp-state-message>\n </div>\n } @else if (vm.error()) {\n <div class=\"__error\">\n <axp-state-message icon=\"fa-light fa-exclamation-triangle\"\n [title]=\"('@assessment-management:questionnaires.components.questionnaire-viewer.error.title' | translate | async) || ''\"\n [description]=\"vm.error() || ''\">\n </axp-state-message>\n </div>\n } @else if (vm.questionnaireData()) {\n <div class=\"__questionnaire-container\">\n <ax-form #form>\n @if (vm.viewMode() === 'single-page') {\n <axm-questionnaire-viewer-single-page-view></axm-questionnaire-viewer-single-page-view>\n } @else if (vm.viewMode() === 'page-per-group') {\n <axm-questionnaire-viewer-page-per-group-view></axm-questionnaire-viewer-page-per-group-view>\n } @else if (vm.viewMode() === 'page-per-question') {\n <axm-questionnaire-viewer-page-per-question-view></axm-questionnaire-viewer-page-per-question-view>\n } @else if (vm.viewMode() === 'side-menu') {\n <axm-questionnaire-viewer-side-menu-view></axm-questionnaire-viewer-side-menu-view>\n }\n </ax-form>\n </div>\n }\n</axp-widgets-container>\n", styles: [".axm-questionnaire-viewer{display:flex;height:100%;max-height:100%;min-height:0px;width:100%;flex:1 1 0%;flex-direction:column}.axm-questionnaire-viewer ax-form{display:flex;height:100%;min-height:0px;flex:1 1 0%;flex-direction:column}.axm-questionnaire-viewer axp-widgets-container{display:flex;height:100%;min-height:0px;flex:1 1 0%;flex-direction:column}.axm-questionnaire-viewer .__loading,.axm-questionnaire-viewer .__error{display:flex;height:100%;align-items:center;justify-content:center}.axm-questionnaire-viewer .__questionnaire-container{display:flex;min-height:0px;flex:1 1 0%;flex-direction:column;overflow:hidden}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "component", type: AXPStateMessageComponent, selector: "axp-state-message", inputs: ["mode", "icon", "title", "description", "look"] }, { kind: "ngmodule", type: AXFormModule }, { kind: "component", type: i1$3.AXFormComponent, selector: "ax-form", inputs: ["disabled", "readonly", "labelMode", "look", "messageStyle", "updateOn", "inUserInteractionActive"], outputs: ["onValidate", "updateOnChange"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "ngmodule", type: AXPWidgetCoreModule }, { kind: "component", type: i1$1.AXPWidgetContainerComponent, selector: "axp-widgets-container", inputs: ["context", "functions"], outputs: ["onContextChanged"] }, { kind: "component", type:
|
|
4187
7310
|
// View components
|
|
4188
|
-
AXMQuestionnaireViewerSinglePageViewComponent, selector: "axm-questionnaire-viewer-single-page-view" }, { kind: "component", type: AXMQuestionnaireViewerPagePerGroupViewComponent, selector: "axm-questionnaire-viewer-page-per-group-view" }, { kind: "component", type: AXMQuestionnaireViewerPagePerQuestionViewComponent, selector: "axm-questionnaire-viewer-page-per-question-view" }, { kind: "component", type: AXMQuestionnaireViewerSideMenuViewComponent, selector: "axm-questionnaire-viewer-side-menu-view" }, { kind: "pipe", type: i3.AsyncPipe, name: "async" }, { kind: "pipe", type: i4
|
|
7311
|
+
AXMQuestionnaireViewerSinglePageViewComponent, selector: "axm-questionnaire-viewer-single-page-view" }, { kind: "component", type: AXMQuestionnaireViewerPagePerGroupViewComponent, selector: "axm-questionnaire-viewer-page-per-group-view" }, { kind: "component", type: AXMQuestionnaireViewerPagePerQuestionViewComponent, selector: "axm-questionnaire-viewer-page-per-question-view" }, { kind: "component", type: AXMQuestionnaireViewerSideMenuViewComponent, selector: "axm-questionnaire-viewer-side-menu-view" }, { kind: "pipe", type: i3.AsyncPipe, name: "async" }, { kind: "pipe", type: i4.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
|
|
4189
7312
|
}
|
|
4190
7313
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMQuestionnaireViewerComponent, decorators: [{
|
|
4191
7314
|
type: Component,
|
|
@@ -4255,7 +7378,6 @@ class AXMQuestionnaireEvaluatorScopeProvider {
|
|
|
4255
7378
|
async provide(context) {
|
|
4256
7379
|
const questionnaireEntity = `${RootConfig.module.name}.${RootConfig.entities.questionnaire.name}`;
|
|
4257
7380
|
const questionBankEntity = `${RootConfig.module.name}.${RootConfig.entities.questionBankItem.name}`;
|
|
4258
|
-
const questionnaireCalculationEntity = `${RootConfig.module.name}.${RootConfig.entities.questionnaireCalculation.name}`;
|
|
4259
7381
|
const filterDefinitionsImpl = async (questionnaireId) => {
|
|
4260
7382
|
if (!questionnaireId) {
|
|
4261
7383
|
return [];
|
|
@@ -4346,27 +7468,20 @@ class AXMQuestionnaireEvaluatorScopeProvider {
|
|
|
4346
7468
|
return [];
|
|
4347
7469
|
}
|
|
4348
7470
|
};
|
|
4349
|
-
/** Filter definitions from questionnaire
|
|
7471
|
+
/** Filter definitions from embedded questionnaire outcomes (for automation condition: rules.ruleName). */
|
|
4350
7472
|
const forRules = async (questionnaireId) => {
|
|
4351
7473
|
if (!questionnaireId) {
|
|
4352
7474
|
return [];
|
|
4353
7475
|
}
|
|
4354
7476
|
try {
|
|
4355
|
-
const dataAccessor = this.entityService.withEntity(
|
|
4356
|
-
const
|
|
4357
|
-
|
|
4358
|
-
|
|
4359
|
-
filter: {
|
|
4360
|
-
field: 'questionnaireId',
|
|
4361
|
-
operator: { type: 'equal' },
|
|
4362
|
-
value: questionnaireId,
|
|
4363
|
-
},
|
|
4364
|
-
});
|
|
4365
|
-
const rules = (queryResult?.items ?? []);
|
|
7477
|
+
const dataAccessor = this.entityService.withEntity(questionnaireEntity).data();
|
|
7478
|
+
const questionnaire = await dataAccessor.byKey(questionnaireId);
|
|
7479
|
+
const rules = flattenQuestionnaireOutcomeItems(questionnaire?.outcomes);
|
|
7480
|
+
const locale = this.translationService.getActiveLang() ?? 'en-US';
|
|
4366
7481
|
return rules.map((rule, order) => ({
|
|
4367
7482
|
id: rule.id,
|
|
4368
7483
|
field: `rules.${rule.name}`,
|
|
4369
|
-
title: rule.title
|
|
7484
|
+
title: resolveMultiLanguageString(rule.title, locale) || rule.name,
|
|
4370
7485
|
operator: { type: 'equal' },
|
|
4371
7486
|
widget: {
|
|
4372
7487
|
type: 'string-filter',
|
|
@@ -4389,7 +7504,7 @@ class AXMQuestionnaireEvaluatorScopeProvider {
|
|
|
4389
7504
|
context.addScope('questionnaire', {
|
|
4390
7505
|
/** Filter definitions from questionnaire answers (e.g. visibility / automation conditions). */
|
|
4391
7506
|
answers: filterDefinitionsImpl,
|
|
4392
|
-
/** Filter definitions from questionnaire
|
|
7507
|
+
/** Filter definitions from questionnaire outcomes for automation condition builder (rules.ruleName). */
|
|
4393
7508
|
rules: forRules,
|
|
4394
7509
|
});
|
|
4395
7510
|
// Automation condition builder: provide rules for refType = AssessmentManagement.Questionnaire
|
|
@@ -4422,31 +7537,27 @@ class AXMQuestionnaireViewerFeatureModule {
|
|
|
4422
7537
|
provideCommandSetups([
|
|
4423
7538
|
{
|
|
4424
7539
|
key: `${RootConfig.module.name}.${RootConfig.entities.questionnaire.name}:Preview`,
|
|
4425
|
-
command: () => import('./acorex-modules-assessment-management-preview-questionnaire.command-
|
|
7540
|
+
command: () => import('./acorex-modules-assessment-management-preview-questionnaire.command-CRDBe_BS.mjs').then((c) => c.PreviewQuestionnaireCommand),
|
|
4426
7541
|
},
|
|
4427
7542
|
{
|
|
4428
7543
|
key: `${RootConfig.module.name}.${RootConfig.entities.questionnaire.name}:PreviewQuestion`,
|
|
4429
|
-
command: () => import('./acorex-modules-assessment-management-preview-question.command-
|
|
7544
|
+
command: () => import('./acorex-modules-assessment-management-preview-question.command-6IGOdVVZ.mjs').then((c) => c.PreviewQuestionCommand),
|
|
4430
7545
|
},
|
|
4431
7546
|
{
|
|
4432
7547
|
key: `${RootConfig.module.name}.${RootConfig.entities.questionBankItem.name}:Preview`,
|
|
4433
|
-
command: () => import('./acorex-modules-assessment-management-preview-question.command-
|
|
7548
|
+
command: () => import('./acorex-modules-assessment-management-preview-question.command-6IGOdVVZ.mjs').then((c) => c.PreviewQuestionCommand),
|
|
4434
7549
|
},
|
|
4435
7550
|
{
|
|
4436
7551
|
key: `${RootConfig.module.name}.${RootConfig.entities.assessmentSession.name}:ViewAnswers`,
|
|
4437
|
-
command: () => import('./acorex-modules-assessment-management-view-session-answers.command-
|
|
7552
|
+
command: () => import('./acorex-modules-assessment-management-view-session-answers.command-BOeO3Dit.mjs').then((c) => c.ViewSessionAnswersCommand),
|
|
4438
7553
|
},
|
|
4439
7554
|
{
|
|
4440
7555
|
key: `${RootConfig.module.name}.${RootConfig.entities.assessmentSession.name}:Fill`,
|
|
4441
|
-
command: () => import('./acorex-modules-assessment-management-fill-assessment-session.command-
|
|
7556
|
+
command: () => import('./acorex-modules-assessment-management-fill-assessment-session.command-4fkaeAG-.mjs').then((c) => c.FillAssessmentSessionCommand),
|
|
4442
7557
|
},
|
|
4443
7558
|
{
|
|
4444
7559
|
key: `${RootConfig.module.name}.${RootConfig.entities.assessmentCase.name}:Fill`,
|
|
4445
|
-
command: () => import('./acorex-modules-assessment-management-fill-assessment-session.command-
|
|
4446
|
-
},
|
|
4447
|
-
{
|
|
4448
|
-
key: `${RootConfig.module.name}.${RootConfig.entities.assessmentCase.name}:ViewLastSessionAnswers`,
|
|
4449
|
-
command: () => import('./acorex-modules-assessment-management-view-case-last-session-answers.command-NTuDdoYk.mjs').then((c) => c.ViewCaseLastSessionAnswersCommand),
|
|
7560
|
+
command: () => import('./acorex-modules-assessment-management-fill-assessment-session.command-4fkaeAG-.mjs').then((c) => c.FillAssessmentSessionCommand),
|
|
4450
7561
|
},
|
|
4451
7562
|
]),
|
|
4452
7563
|
], imports: [AXPWidgetCoreModule,
|
|
@@ -4473,31 +7584,27 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
|
|
|
4473
7584
|
provideCommandSetups([
|
|
4474
7585
|
{
|
|
4475
7586
|
key: `${RootConfig.module.name}.${RootConfig.entities.questionnaire.name}:Preview`,
|
|
4476
|
-
command: () => import('./acorex-modules-assessment-management-preview-questionnaire.command-
|
|
7587
|
+
command: () => import('./acorex-modules-assessment-management-preview-questionnaire.command-CRDBe_BS.mjs').then((c) => c.PreviewQuestionnaireCommand),
|
|
4477
7588
|
},
|
|
4478
7589
|
{
|
|
4479
7590
|
key: `${RootConfig.module.name}.${RootConfig.entities.questionnaire.name}:PreviewQuestion`,
|
|
4480
|
-
command: () => import('./acorex-modules-assessment-management-preview-question.command-
|
|
7591
|
+
command: () => import('./acorex-modules-assessment-management-preview-question.command-6IGOdVVZ.mjs').then((c) => c.PreviewQuestionCommand),
|
|
4481
7592
|
},
|
|
4482
7593
|
{
|
|
4483
7594
|
key: `${RootConfig.module.name}.${RootConfig.entities.questionBankItem.name}:Preview`,
|
|
4484
|
-
command: () => import('./acorex-modules-assessment-management-preview-question.command-
|
|
7595
|
+
command: () => import('./acorex-modules-assessment-management-preview-question.command-6IGOdVVZ.mjs').then((c) => c.PreviewQuestionCommand),
|
|
4485
7596
|
},
|
|
4486
7597
|
{
|
|
4487
7598
|
key: `${RootConfig.module.name}.${RootConfig.entities.assessmentSession.name}:ViewAnswers`,
|
|
4488
|
-
command: () => import('./acorex-modules-assessment-management-view-session-answers.command-
|
|
7599
|
+
command: () => import('./acorex-modules-assessment-management-view-session-answers.command-BOeO3Dit.mjs').then((c) => c.ViewSessionAnswersCommand),
|
|
4489
7600
|
},
|
|
4490
7601
|
{
|
|
4491
7602
|
key: `${RootConfig.module.name}.${RootConfig.entities.assessmentSession.name}:Fill`,
|
|
4492
|
-
command: () => import('./acorex-modules-assessment-management-fill-assessment-session.command-
|
|
7603
|
+
command: () => import('./acorex-modules-assessment-management-fill-assessment-session.command-4fkaeAG-.mjs').then((c) => c.FillAssessmentSessionCommand),
|
|
4493
7604
|
},
|
|
4494
7605
|
{
|
|
4495
7606
|
key: `${RootConfig.module.name}.${RootConfig.entities.assessmentCase.name}:Fill`,
|
|
4496
|
-
command: () => import('./acorex-modules-assessment-management-fill-assessment-session.command-
|
|
4497
|
-
},
|
|
4498
|
-
{
|
|
4499
|
-
key: `${RootConfig.module.name}.${RootConfig.entities.assessmentCase.name}:ViewLastSessionAnswers`,
|
|
4500
|
-
command: () => import('./acorex-modules-assessment-management-view-case-last-session-answers.command-NTuDdoYk.mjs').then((c) => c.ViewCaseLastSessionAnswersCommand),
|
|
7607
|
+
command: () => import('./acorex-modules-assessment-management-fill-assessment-session.command-4fkaeAG-.mjs').then((c) => c.FillAssessmentSessionCommand),
|
|
4501
7608
|
},
|
|
4502
7609
|
]),
|
|
4503
7610
|
],
|
|
@@ -4550,8 +7657,10 @@ class AXMAssessmentManagementModule {
|
|
|
4550
7657
|
provideLazyProvider(AXP_PERMISSION_DEFINITION_PROVIDER, () => Promise.resolve().then(function () { return permissionDefinition_provider; }).then((m) => m.AXMAssessmentManagementPermissionDefinitionProvider)),
|
|
4551
7658
|
provideLazyProvider(AXP_MENU_PROVIDER, () => Promise.resolve().then(function () { return menu_provider; }).then((m) => m.AXMAssessmentManagementMenuProvider)),
|
|
4552
7659
|
provideLazyProvider(AXP_ENTITY_DEFINITION_LOADER, () => Promise.resolve().then(function () { return entity_provider; }).then((m) => m.AXMAssessmentManagementEntityProvider)),
|
|
4553
|
-
provideLazyProvider(AXP_PAGE_COMPONENT_PROVIDER, () =>
|
|
4554
|
-
|
|
7660
|
+
provideLazyProvider(AXP_PAGE_COMPONENT_PROVIDER, () => Promise.resolve().then(function () { return index$1; }).then((m) => m.AXMQuestionnaireQuestionsPageComponentProvider)),
|
|
7661
|
+
provideLazyProvider(AXP_PAGE_COMPONENT_PROVIDER, () => Promise.resolve().then(function () { return index; }).then((m) => m.AXMQuestionnaireOutcomesPageComponentProvider)),
|
|
7662
|
+
provideCommand('Questionnaire:Questions:Save', () => Promise.resolve().then(function () { return saveQuestionnaireQuestions_command; }).then((m) => m.AXMSaveQuestionnaireQuestionsCommand)),
|
|
7663
|
+
provideCommand('Questionnaire:Outcomes:Save', () => Promise.resolve().then(function () { return saveQuestionnaireOutcomes_command; }).then((m) => m.AXMSaveQuestionnaireOutcomesCommand)),
|
|
4555
7664
|
provideLazyProvider(AXP_SEARCH_PROVIDER, () => Promise.resolve().then(function () { return searchCommand_provider; }).then((m) => m.AXMAssessmentManagementSearchCommandProvider)),
|
|
4556
7665
|
], imports: [AXMQuestionnaireBuilderFeatureModule,
|
|
4557
7666
|
AXMQuestionnaireViewerFeatureModule] }); }
|
|
@@ -4583,8 +7692,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
|
|
|
4583
7692
|
provideLazyProvider(AXP_PERMISSION_DEFINITION_PROVIDER, () => Promise.resolve().then(function () { return permissionDefinition_provider; }).then((m) => m.AXMAssessmentManagementPermissionDefinitionProvider)),
|
|
4584
7693
|
provideLazyProvider(AXP_MENU_PROVIDER, () => Promise.resolve().then(function () { return menu_provider; }).then((m) => m.AXMAssessmentManagementMenuProvider)),
|
|
4585
7694
|
provideLazyProvider(AXP_ENTITY_DEFINITION_LOADER, () => Promise.resolve().then(function () { return entity_provider; }).then((m) => m.AXMAssessmentManagementEntityProvider)),
|
|
4586
|
-
provideLazyProvider(AXP_PAGE_COMPONENT_PROVIDER, () =>
|
|
4587
|
-
|
|
7695
|
+
provideLazyProvider(AXP_PAGE_COMPONENT_PROVIDER, () => Promise.resolve().then(function () { return index$1; }).then((m) => m.AXMQuestionnaireQuestionsPageComponentProvider)),
|
|
7696
|
+
provideLazyProvider(AXP_PAGE_COMPONENT_PROVIDER, () => Promise.resolve().then(function () { return index; }).then((m) => m.AXMQuestionnaireOutcomesPageComponentProvider)),
|
|
7697
|
+
provideCommand('Questionnaire:Questions:Save', () => Promise.resolve().then(function () { return saveQuestionnaireQuestions_command; }).then((m) => m.AXMSaveQuestionnaireQuestionsCommand)),
|
|
7698
|
+
provideCommand('Questionnaire:Outcomes:Save', () => Promise.resolve().then(function () { return saveQuestionnaireOutcomes_command; }).then((m) => m.AXMSaveQuestionnaireOutcomesCommand)),
|
|
4588
7699
|
provideLazyProvider(AXP_SEARCH_PROVIDER, () => Promise.resolve().then(function () { return searchCommand_provider; }).then((m) => m.AXMAssessmentManagementSearchCommandProvider)),
|
|
4589
7700
|
],
|
|
4590
7701
|
}]
|
|
@@ -4593,109 +7704,136 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
|
|
|
4593
7704
|
//#region ---- QuestionBankItem Model ----
|
|
4594
7705
|
//#endregion
|
|
4595
7706
|
|
|
7707
|
+
//#region ---- Types ----
|
|
7708
|
+
//#endregion
|
|
7709
|
+
|
|
7710
|
+
//#region ---- Types ----
|
|
7711
|
+
//#endregion
|
|
7712
|
+
|
|
4596
7713
|
//#region ---- Imports ----
|
|
4597
|
-
|
|
4598
|
-
|
|
4599
|
-
reviewEnabled: false,
|
|
4600
|
-
summaryEnabled: false,
|
|
4601
|
-
showCalculationResults: false,
|
|
4602
|
-
};
|
|
4603
|
-
const DEFAULT_QUESTIONNAIRE_ENTITY_DISPLAY = {
|
|
4604
|
-
viewMode: 'single-page',
|
|
4605
|
-
showProgressBar: true,
|
|
4606
|
-
showTimer: false,
|
|
4607
|
-
showQuestionNumbers: true,
|
|
4608
|
-
validationStrategy: 'step',
|
|
4609
|
-
completionMode: 'submit-only',
|
|
4610
|
-
};
|
|
7714
|
+
//#endregion
|
|
7715
|
+
//#region ---- Persistence ----
|
|
4611
7716
|
/**
|
|
4612
|
-
*
|
|
7717
|
+
* Loads a session by id using list query first, then byKey.
|
|
4613
7718
|
*/
|
|
4614
|
-
function
|
|
4615
|
-
|
|
4616
|
-
|
|
7719
|
+
async function loadSessionById(entityService, sessionId) {
|
|
7720
|
+
const sessionAccessor = entityService
|
|
7721
|
+
.withEntity(RootConfig.module.name, RootConfig.entities.assessmentSession.name)
|
|
7722
|
+
.data();
|
|
7723
|
+
const listMatch = await sessionAccessor.query({
|
|
7724
|
+
skip: 0,
|
|
7725
|
+
take: 1,
|
|
7726
|
+
filter: {
|
|
7727
|
+
field: 'id',
|
|
7728
|
+
operator: { type: 'equal' },
|
|
7729
|
+
value: sessionId,
|
|
7730
|
+
},
|
|
7731
|
+
});
|
|
7732
|
+
const fromQuery = first(listMatch.items);
|
|
7733
|
+
if (fromQuery) {
|
|
7734
|
+
return fromQuery;
|
|
4617
7735
|
}
|
|
4618
|
-
|
|
4619
|
-
...DEFAULT_PRE_QUESTIONNAIRE_CONFIG,
|
|
4620
|
-
...q.pre,
|
|
4621
|
-
enabled: q.pre?.enabled === true,
|
|
4622
|
-
};
|
|
4623
|
-
const post = {
|
|
4624
|
-
...DEFAULT_POST_QUESTIONNAIRE_CONFIG,
|
|
4625
|
-
...q.post,
|
|
4626
|
-
reviewEnabled: q.post?.reviewEnabled === true,
|
|
4627
|
-
summaryEnabled: q.post?.summaryEnabled === true,
|
|
4628
|
-
showCalculationResults: q.post?.showCalculationResults === true,
|
|
4629
|
-
};
|
|
4630
|
-
return { pre, post };
|
|
7736
|
+
return defaultTo(await sessionAccessor.byKey(sessionId), null);
|
|
4631
7737
|
}
|
|
4632
|
-
const VIEW_MODE_VALUES = ['single-page', 'page-per-group', 'page-per-question', 'side-menu'];
|
|
4633
|
-
const VALIDATION_STRATEGY_VALUES = ['step', 'end'];
|
|
4634
|
-
const COMPLETION_MODE_VALUES = ['submit-only', 'save-and-continue'];
|
|
4635
7738
|
/**
|
|
4636
|
-
*
|
|
7739
|
+
* Loads assessment case by id using query first, then byKey.
|
|
4637
7740
|
*/
|
|
4638
|
-
function
|
|
4639
|
-
|
|
4640
|
-
|
|
4641
|
-
|
|
4642
|
-
|
|
4643
|
-
|
|
7741
|
+
async function loadCaseById(entityService, caseId) {
|
|
7742
|
+
const caseAccessor = entityService
|
|
7743
|
+
.withEntity(RootConfig.module.name, RootConfig.entities.assessmentCase.name)
|
|
7744
|
+
.data();
|
|
7745
|
+
const listMatch = await caseAccessor.query({
|
|
7746
|
+
skip: 0,
|
|
7747
|
+
take: 1,
|
|
7748
|
+
filter: {
|
|
7749
|
+
field: 'id',
|
|
7750
|
+
operator: { type: 'equal' },
|
|
7751
|
+
value: caseId,
|
|
7752
|
+
},
|
|
7753
|
+
});
|
|
7754
|
+
const fromQuery = first(listMatch.items);
|
|
7755
|
+
if (fromQuery) {
|
|
7756
|
+
return fromQuery;
|
|
4644
7757
|
}
|
|
4645
|
-
return
|
|
7758
|
+
return defaultTo(await caseAccessor.byKey(caseId), null);
|
|
4646
7759
|
}
|
|
4647
7760
|
/**
|
|
4648
|
-
*
|
|
7761
|
+
* Bumps case audit metadata by performing a domain update (history middleware sets auditInfo.updated.at).
|
|
4649
7762
|
*/
|
|
4650
|
-
function
|
|
4651
|
-
|
|
4652
|
-
|
|
4653
|
-
|
|
4654
|
-
|
|
4655
|
-
|
|
4656
|
-
|
|
4657
|
-
|
|
7763
|
+
async function touchAssessmentCaseActivity(entityService, caseId) {
|
|
7764
|
+
const assessmentCase = await loadCaseById(entityService, caseId);
|
|
7765
|
+
if (!assessmentCase) {
|
|
7766
|
+
return;
|
|
7767
|
+
}
|
|
7768
|
+
const caseAccessor = entityService
|
|
7769
|
+
.withEntity(RootConfig.module.name, RootConfig.entities.assessmentCase.name)
|
|
7770
|
+
.data();
|
|
7771
|
+
const caseStatus = assessmentCase.statusId;
|
|
7772
|
+
const nextCaseStatus = caseStatus === AXPSystemStatusType.Closed || caseStatus === AXPSystemStatusType.Cancelled
|
|
7773
|
+
? caseStatus
|
|
7774
|
+
: AXPSystemStatusType.InProgress;
|
|
7775
|
+
await caseAccessor.update(caseId, { statusId: nextCaseStatus });
|
|
4658
7776
|
}
|
|
4659
7777
|
/**
|
|
4660
|
-
*
|
|
7778
|
+
* Upserts assessment session answers and status; moves case to in-progress when saving or submitting.
|
|
4661
7779
|
*/
|
|
4662
|
-
function
|
|
4663
|
-
|
|
4664
|
-
|
|
7780
|
+
async function persistAssessmentSession(input) {
|
|
7781
|
+
const { entityService, questionnaireViewerService, caseId, sessionId, existingSession, responderId, role, structure, answers, finalize, progressMetrics, timeSpentSeconds, } = input;
|
|
7782
|
+
const calculatedProgress = questionnaireViewerService.calculateProgressFromStructure(structure, answers);
|
|
7783
|
+
const answeredQuestionsCount = defaultTo(get(progressMetrics, 'answeredQuestionsCount'), calculatedProgress.answeredQuestionsCount);
|
|
7784
|
+
const progressPercentage = defaultTo(get(progressMetrics, 'progressPercentage'), calculatedProgress.progressPercentage);
|
|
7785
|
+
const now = new Date();
|
|
7786
|
+
const sessionAccessor = entityService
|
|
7787
|
+
.withEntity(RootConfig.module.name, RootConfig.entities.assessmentSession.name)
|
|
7788
|
+
.data();
|
|
7789
|
+
let resolvedSessionId = sessionId;
|
|
7790
|
+
let currentSession = existingSession;
|
|
7791
|
+
if (resolvedSessionId && !currentSession) {
|
|
7792
|
+
currentSession = await loadSessionById(entityService, resolvedSessionId);
|
|
7793
|
+
}
|
|
7794
|
+
const sessionStatusId = finalize
|
|
7795
|
+
? 'submitted'
|
|
7796
|
+
: get(currentSession, 'statusId') === 'submitted'
|
|
7797
|
+
? 'submitted'
|
|
7798
|
+
: AXPSystemStatusType.InProgress;
|
|
7799
|
+
const sessionData = {
|
|
7800
|
+
caseId,
|
|
7801
|
+
responderId,
|
|
7802
|
+
role,
|
|
7803
|
+
answers,
|
|
7804
|
+
progressPercentage,
|
|
7805
|
+
answeredQuestionsCount,
|
|
7806
|
+
lastSavedAt: now,
|
|
7807
|
+
statusId: sessionStatusId,
|
|
7808
|
+
};
|
|
7809
|
+
if (isEmpty(get(currentSession, 'startedAt'))) {
|
|
7810
|
+
sessionData['startedAt'] = now;
|
|
4665
7811
|
}
|
|
4666
|
-
if (
|
|
4667
|
-
|
|
7812
|
+
if (timeSpentSeconds != null && timeSpentSeconds >= 0) {
|
|
7813
|
+
sessionData['timeSpent'] = timeSpentSeconds;
|
|
4668
7814
|
}
|
|
4669
|
-
|
|
4670
|
-
|
|
4671
|
-
|
|
4672
|
-
|
|
4673
|
-
|
|
4674
|
-
|
|
4675
|
-
|
|
4676
|
-
|
|
7815
|
+
const questionnaireId = input.questionnaireId;
|
|
7816
|
+
if (questionnaireId) {
|
|
7817
|
+
const { values } = await questionnaireViewerService.evaluateOutcomes(answers, {
|
|
7818
|
+
questionnaireId,
|
|
7819
|
+
structure,
|
|
7820
|
+
});
|
|
7821
|
+
if (isObject(values) && !isEmpty(values)) {
|
|
7822
|
+
sessionData['outcomes'] = values;
|
|
7823
|
+
}
|
|
4677
7824
|
}
|
|
4678
|
-
|
|
4679
|
-
|
|
4680
|
-
|
|
4681
|
-
|
|
4682
|
-
|
|
4683
|
-
|
|
4684
|
-
|
|
4685
|
-
|
|
4686
|
-
};
|
|
7825
|
+
if (resolvedSessionId) {
|
|
7826
|
+
await sessionAccessor.update(resolvedSessionId, sessionData);
|
|
7827
|
+
}
|
|
7828
|
+
else {
|
|
7829
|
+
sessionData['startedAt'] = now;
|
|
7830
|
+
resolvedSessionId = await sessionAccessor.create(sessionData);
|
|
7831
|
+
}
|
|
7832
|
+
await touchAssessmentCaseActivity(entityService, caseId);
|
|
7833
|
+
return { sessionId: resolvedSessionId };
|
|
4687
7834
|
}
|
|
4688
7835
|
//#endregion
|
|
4689
7836
|
|
|
4690
|
-
//#region ---- Types ----
|
|
4691
|
-
//#endregion
|
|
4692
|
-
|
|
4693
|
-
//#region ---- Types ----
|
|
4694
|
-
//#endregion
|
|
4695
|
-
|
|
4696
|
-
//#region ---- Types ----
|
|
4697
|
-
//#endregion
|
|
4698
|
-
|
|
4699
7837
|
//#region ---- Imports ----
|
|
4700
7838
|
//#endregion
|
|
4701
7839
|
//#region ---- Component ----
|
|
@@ -4720,7 +7858,7 @@ class AXMPreQuestionnaireContentComponent {
|
|
|
4720
7858
|
[innerHTML]="content() | translate | async | safe: 'html'"
|
|
4721
7859
|
></div>
|
|
4722
7860
|
</div>
|
|
4723
|
-
`, isInline: true, dependencies: [{ kind: "ngmodule", type: AXTranslationModule }, { kind: "pipe", type: i4
|
|
7861
|
+
`, isInline: true, dependencies: [{ kind: "ngmodule", type: AXTranslationModule }, { kind: "pipe", type: i4.AXTranslatorPipe, name: "translate" }, { kind: "pipe", type: AXSafePipe, name: "safe" }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
|
|
4724
7862
|
}
|
|
4725
7863
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMPreQuestionnaireContentComponent, decorators: [{
|
|
4726
7864
|
type: Component,
|
|
@@ -4743,6 +7881,166 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
|
|
|
4743
7881
|
}]
|
|
4744
7882
|
}], propDecorators: { content: [{ type: i0.Input, args: [{ isSignal: true, alias: "content", required: false }] }] } });
|
|
4745
7883
|
|
|
7884
|
+
//#region ---- Imports ----
|
|
7885
|
+
//#endregion
|
|
7886
|
+
//#region ---- Presentation ----
|
|
7887
|
+
/**
|
|
7888
|
+
* Maps questionnaire outcome display metadata to platform value chip classes/styles.
|
|
7889
|
+
*/
|
|
7890
|
+
function mapOutcomeDisplayToValuePresentation(display) {
|
|
7891
|
+
const classes = ['__outcome-value'];
|
|
7892
|
+
if (display?.emphasis === 'medium') {
|
|
7893
|
+
classes.push('__emphasis-medium');
|
|
7894
|
+
}
|
|
7895
|
+
else if (display?.emphasis === 'bold') {
|
|
7896
|
+
classes.push('__emphasis-bold');
|
|
7897
|
+
}
|
|
7898
|
+
if (!display?.color) {
|
|
7899
|
+
classes.push('__tone-default');
|
|
7900
|
+
return { classes: classes.join(' ') };
|
|
7901
|
+
}
|
|
7902
|
+
const parsed = parseQuestionnaireOutcomeDisplayColor(display.color);
|
|
7903
|
+
if (!parsed) {
|
|
7904
|
+
classes.push('__tone-default');
|
|
7905
|
+
return { classes: classes.join(' ') };
|
|
7906
|
+
}
|
|
7907
|
+
if (isQuestionnaireOutcomeDisplayColorHex(parsed.background)) {
|
|
7908
|
+
return {
|
|
7909
|
+
classes: classes.join(' '),
|
|
7910
|
+
color: parsed.foreground,
|
|
7911
|
+
backgroundColor: parsed.background,
|
|
7912
|
+
borderColor: parsed.border,
|
|
7913
|
+
};
|
|
7914
|
+
}
|
|
7915
|
+
return {
|
|
7916
|
+
classes: [...classes, parsed.foreground, parsed.background, parsed.border].join(' '),
|
|
7917
|
+
};
|
|
7918
|
+
}
|
|
7919
|
+
function mapOutcomeRow(entry) {
|
|
7920
|
+
return {
|
|
7921
|
+
key: entry.key,
|
|
7922
|
+
label: entry.label,
|
|
7923
|
+
value: entry.value,
|
|
7924
|
+
iconClass: entry.display?.iconClass,
|
|
7925
|
+
valuePresentation: mapOutcomeDisplayToValuePresentation(entry.display),
|
|
7926
|
+
};
|
|
7927
|
+
}
|
|
7928
|
+
function resolveSectionText(value, locale, fallback) {
|
|
7929
|
+
const resolved = resolveMultiLanguageString(value, locale).trim();
|
|
7930
|
+
return resolved.length > 0 ? resolved : fallback;
|
|
7931
|
+
}
|
|
7932
|
+
//#endregion
|
|
7933
|
+
//#region ---- View model ----
|
|
7934
|
+
/**
|
|
7935
|
+
* Maps post-submit placeholder values or snapshot sections to {@link AXPOutcomeResultsViewModel}.
|
|
7936
|
+
*/
|
|
7937
|
+
function mapToOutcomeResultsViewModel(source, options) {
|
|
7938
|
+
const locale = options?.locale ?? 'en-US';
|
|
7939
|
+
const sections = source?.outcomeSections;
|
|
7940
|
+
if (Array.isArray(sections) && sections.length > 0) {
|
|
7941
|
+
return {
|
|
7942
|
+
sections: sections.map((group) => mapSectionGroup(group, locale)),
|
|
7943
|
+
rows: sections.length === 1 ? sections[0].items.map(mapOutcomeRow) : undefined,
|
|
7944
|
+
};
|
|
7945
|
+
}
|
|
7946
|
+
const outcomes = source?.outcomes;
|
|
7947
|
+
const titles = source?.outcomeTitles;
|
|
7948
|
+
if (!outcomes || typeof outcomes !== 'object') {
|
|
7949
|
+
return { rows: [] };
|
|
7950
|
+
}
|
|
7951
|
+
const rows = Object.entries(outcomes).map(([key, value]) => mapOutcomeRow({
|
|
7952
|
+
key,
|
|
7953
|
+
value,
|
|
7954
|
+
label: (titles?.[key] ?? '').trim() || humanizeOutcomeKey(key),
|
|
7955
|
+
}));
|
|
7956
|
+
return { rows };
|
|
7957
|
+
}
|
|
7958
|
+
function mapSectionGroup(group, locale) {
|
|
7959
|
+
const fallbackTitle = group.sectionName || group.trackKey;
|
|
7960
|
+
return {
|
|
7961
|
+
trackKey: group.trackKey,
|
|
7962
|
+
title: resolveSectionText(group.sectionTitle, locale, fallbackTitle),
|
|
7963
|
+
description: group.sectionDescription
|
|
7964
|
+
? resolveSectionText(group.sectionDescription, locale, '')
|
|
7965
|
+
: undefined,
|
|
7966
|
+
items: group.items.map(mapOutcomeRow),
|
|
7967
|
+
};
|
|
7968
|
+
}
|
|
7969
|
+
function humanizeOutcomeKey(key) {
|
|
7970
|
+
return key
|
|
7971
|
+
.replace(/_/g, ' ')
|
|
7972
|
+
.replace(/([a-z0-9])([A-Z])/g, '$1 $2')
|
|
7973
|
+
.trim()
|
|
7974
|
+
.split(/\s+/)
|
|
7975
|
+
.map((w) => w.charAt(0).toUpperCase() + w.slice(1).toLowerCase())
|
|
7976
|
+
.join(' ');
|
|
7977
|
+
}
|
|
7978
|
+
//#endregion
|
|
7979
|
+
|
|
7980
|
+
//#region ---- Imports ----
|
|
7981
|
+
//#endregion
|
|
7982
|
+
//#region ---- Component ----
|
|
7983
|
+
/**
|
|
7984
|
+
* Post-submit outcome results step; delegates presentation to {@link AXPOutcomeResultsViewerComponent}.
|
|
7985
|
+
*/
|
|
7986
|
+
class AXMQuestionnaireOutcomeResultsComponent {
|
|
7987
|
+
constructor() {
|
|
7988
|
+
//#region ---- Services & Dependencies ----
|
|
7989
|
+
this.translationService = inject(AXTranslationService);
|
|
7990
|
+
//#endregion
|
|
7991
|
+
//#region ---- Inputs ----
|
|
7992
|
+
/** Evaluated outcomes, titles, and optional grouped sections from the viewer service. */
|
|
7993
|
+
this.placeholderValues = input(null, ...(ngDevMode ? [{ debugName: "placeholderValues" }] : /* istanbul ignore next */ []));
|
|
7994
|
+
//#endregion
|
|
7995
|
+
//#region ---- Computed ----
|
|
7996
|
+
this.viewModel = computed(() => {
|
|
7997
|
+
const locale = this.translationService.getActiveLang?.() ?? 'en-US';
|
|
7998
|
+
return mapToOutcomeResultsViewModel(this.placeholderValues(), { locale });
|
|
7999
|
+
}, ...(ngDevMode ? [{ debugName: "viewModel" }] : /* istanbul ignore next */ []));
|
|
8000
|
+
}
|
|
8001
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMQuestionnaireOutcomeResultsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
8002
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.9", type: AXMQuestionnaireOutcomeResultsComponent, isStandalone: true, selector: "axm-questionnaire-outcome-results", inputs: { placeholderValues: { classPropertyName: "placeholderValues", publicName: "placeholderValues", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "axm-questionnaire-outcome-results ax-block" }, ngImport: i0, template: `
|
|
8003
|
+
<axp-outcome-results-viewer
|
|
8004
|
+
[model]="viewModel()"
|
|
8005
|
+
[title]="
|
|
8006
|
+
('@assessment-management:questionnaires.components.questionnaire-viewer.flow.outcomes-section-title'
|
|
8007
|
+
| translate
|
|
8008
|
+
| async) ?? ''
|
|
8009
|
+
"
|
|
8010
|
+
[emptyMessage]="
|
|
8011
|
+
('@assessment-management:questionnaires.components.questionnaire-viewer.flow.no-outcomes'
|
|
8012
|
+
| translate
|
|
8013
|
+
| async) ?? ''
|
|
8014
|
+
"
|
|
8015
|
+
/>
|
|
8016
|
+
`, isInline: true, dependencies: [{ kind: "ngmodule", type: AXTranslationModule }, { kind: "component", type: AXPOutcomeResultsViewerComponent, selector: "axp-outcome-results-viewer", inputs: ["model", "title", "emptyMessage"] }, { kind: "pipe", type: i4.AXTranslatorPipe, name: "translate" }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
|
|
8017
|
+
}
|
|
8018
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMQuestionnaireOutcomeResultsComponent, decorators: [{
|
|
8019
|
+
type: Component,
|
|
8020
|
+
args: [{
|
|
8021
|
+
selector: 'axm-questionnaire-outcome-results',
|
|
8022
|
+
template: `
|
|
8023
|
+
<axp-outcome-results-viewer
|
|
8024
|
+
[model]="viewModel()"
|
|
8025
|
+
[title]="
|
|
8026
|
+
('@assessment-management:questionnaires.components.questionnaire-viewer.flow.outcomes-section-title'
|
|
8027
|
+
| translate
|
|
8028
|
+
| async) ?? ''
|
|
8029
|
+
"
|
|
8030
|
+
[emptyMessage]="
|
|
8031
|
+
('@assessment-management:questionnaires.components.questionnaire-viewer.flow.no-outcomes'
|
|
8032
|
+
| translate
|
|
8033
|
+
| async) ?? ''
|
|
8034
|
+
"
|
|
8035
|
+
/>
|
|
8036
|
+
`,
|
|
8037
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
8038
|
+
imports: [AXTranslationModule, AsyncPipe, AXPOutcomeResultsViewerComponent],
|
|
8039
|
+
encapsulation: ViewEncapsulation.None,
|
|
8040
|
+
host: { class: 'axm-questionnaire-outcome-results ax-block' },
|
|
8041
|
+
}]
|
|
8042
|
+
}], propDecorators: { placeholderValues: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholderValues", required: false }] }] } });
|
|
8043
|
+
|
|
4746
8044
|
//#region ---- Imports ----
|
|
4747
8045
|
//#endregion
|
|
4748
8046
|
//#region ---- Component ----
|
|
@@ -4758,7 +8056,7 @@ class AXMPostQuestionnaireContentComponent {
|
|
|
4758
8056
|
this.translationService = inject(AXTranslationService);
|
|
4759
8057
|
//#endregion
|
|
4760
8058
|
//#region ---- Inputs ----
|
|
4761
|
-
/** Display mode: review, summary (rich text), or results (
|
|
8059
|
+
/** Display mode: review, summary (rich text), or results (outcome list). */
|
|
4762
8060
|
this.mode = input('review', ...(ngDevMode ? [{ debugName: "mode" }] : /* istanbul ignore next */ []));
|
|
4763
8061
|
/** Questions with answers for review mode. */
|
|
4764
8062
|
this.questionsWithAnswers = input([], ...(ngDevMode ? [{ debugName: "questionsWithAnswers" }] : /* istanbul ignore next */ []));
|
|
@@ -4766,7 +8064,7 @@ class AXMPostQuestionnaireContentComponent {
|
|
|
4766
8064
|
this.reviewContext = input(null, ...(ngDevMode ? [{ debugName: "reviewContext" }] : /* istanbul ignore next */ []));
|
|
4767
8065
|
/** Summary content (rich text). Supports multi-language and placeholders. */
|
|
4768
8066
|
this.summaryContent = input(null, ...(ngDevMode ? [{ debugName: "summaryContent" }] : /* istanbul ignore next */ []));
|
|
4769
|
-
/** Placeholder values: totals, time, and
|
|
8067
|
+
/** Placeholder values: totals, time, and outcome values. */
|
|
4770
8068
|
this.placeholderValues = input(null, ...(ngDevMode ? [{ debugName: "placeholderValues" }] : /* istanbul ignore next */ []));
|
|
4771
8069
|
/** Locale for multi-language content. Defaults to active lang. */
|
|
4772
8070
|
this.locale = input(undefined, ...(ngDevMode ? [{ debugName: "locale" }] : /* istanbul ignore next */ []));
|
|
@@ -4807,19 +8105,6 @@ class AXMPostQuestionnaireContentComponent {
|
|
|
4807
8105
|
}
|
|
4808
8106
|
return groups;
|
|
4809
8107
|
}, ...(ngDevMode ? [{ debugName: "reviewSectionGroups" }] : /* istanbul ignore next */ []));
|
|
4810
|
-
/** Calculation name/value pairs for results step; `label` is entity title or humanized name. */
|
|
4811
|
-
this.outcomeEntries = computed(() => {
|
|
4812
|
-
const pv = this.placeholderValues();
|
|
4813
|
-
const o = pv?.outcomes;
|
|
4814
|
-
const titles = pv?.outcomeTitles;
|
|
4815
|
-
if (!o || typeof o !== 'object')
|
|
4816
|
-
return [];
|
|
4817
|
-
return Object.entries(o).map(([key, value]) => ({
|
|
4818
|
-
key,
|
|
4819
|
-
value,
|
|
4820
|
-
label: (titles?.[key] ?? '').trim() || this.humanizeOutcomeKey(key),
|
|
4821
|
-
}));
|
|
4822
|
-
}, ...(ngDevMode ? [{ debugName: "outcomeEntries" }] : /* istanbul ignore next */ []));
|
|
4823
8108
|
this.summaryContentHtml = computed(() => {
|
|
4824
8109
|
const content = this.summaryContent();
|
|
4825
8110
|
const values = this.placeholderValues();
|
|
@@ -4836,16 +8121,6 @@ class AXMPostQuestionnaireContentComponent {
|
|
|
4836
8121
|
}
|
|
4837
8122
|
//#endregion
|
|
4838
8123
|
//#region ---- Helpers ----
|
|
4839
|
-
/** Fallback when no calculation entity title is available. */
|
|
4840
|
-
humanizeOutcomeKey(key) {
|
|
4841
|
-
return key
|
|
4842
|
-
.replace(/_/g, ' ')
|
|
4843
|
-
.replace(/([a-z0-9])([A-Z])/g, '$1 $2')
|
|
4844
|
-
.trim()
|
|
4845
|
-
.split(/\s+/)
|
|
4846
|
-
.map((w) => w.charAt(0).toUpperCase() + w.slice(1).toLowerCase())
|
|
4847
|
-
.join(' ');
|
|
4848
|
-
}
|
|
4849
8124
|
formatAnswer(answer) {
|
|
4850
8125
|
if (answer == null || answer === '')
|
|
4851
8126
|
return '—';
|
|
@@ -4934,43 +8209,7 @@ class AXMPostQuestionnaireContentComponent {
|
|
|
4934
8209
|
</div>
|
|
4935
8210
|
</div>
|
|
4936
8211
|
} @else if (mode() === 'results') {
|
|
4937
|
-
<
|
|
4938
|
-
class="axm-post-questionnaire-content __results ax-flex ax-flex-col ax-items-center ax-justify-center ax-p-8 ax-min-h-[200px] ax-text-on-surface"
|
|
4939
|
-
>
|
|
4940
|
-
@if (outcomeEntries().length > 0) {
|
|
4941
|
-
<div class="ax-max-w-2xl ax-w-full">
|
|
4942
|
-
<h3 class="ax-text-base ax-font-semibold ax-mb-3 ax-text-on-surface">
|
|
4943
|
-
{{
|
|
4944
|
-
'@assessment-management:questionnaires.components.questionnaire-viewer.flow.outcomes-section-title'
|
|
4945
|
-
| translate
|
|
4946
|
-
| async
|
|
4947
|
-
}}
|
|
4948
|
-
</h3>
|
|
4949
|
-
<ul
|
|
4950
|
-
class="ax-list-none ax-p-0 ax-m-0 ax-flex ax-flex-col ax-gap-1 ax-rounded-lg ax-border ax-border-surface ax-lighter-surface ax-overflow-hidden"
|
|
4951
|
-
>
|
|
4952
|
-
@for (row of outcomeEntries(); track row.key) {
|
|
4953
|
-
<li
|
|
4954
|
-
class="ax-flex ax-justify-between ax-gap-4 ax-py-3 ax-px-4 ax-border-b ax-border-surface last:ax-border-b-0"
|
|
4955
|
-
>
|
|
4956
|
-
<span class="ax-text-sm ax-font-medium __post-text-muted">{{ row.label }}</span>
|
|
4957
|
-
<span class="ax-text-sm ax-text-on-surface ax-text-right ax-break-all">{{
|
|
4958
|
-
formatAnswer(row.value)
|
|
4959
|
-
}}</span>
|
|
4960
|
-
</li>
|
|
4961
|
-
}
|
|
4962
|
-
</ul>
|
|
4963
|
-
</div>
|
|
4964
|
-
} @else {
|
|
4965
|
-
<p class="ax-text-sm __post-text-muted">
|
|
4966
|
-
{{
|
|
4967
|
-
'@assessment-management:questionnaires.components.questionnaire-viewer.flow.no-outcomes'
|
|
4968
|
-
| translate
|
|
4969
|
-
| async
|
|
4970
|
-
}}
|
|
4971
|
-
</p>
|
|
4972
|
-
}
|
|
4973
|
-
</div>
|
|
8212
|
+
<axm-questionnaire-outcome-results [placeholderValues]="placeholderValues()" />
|
|
4974
8213
|
} @else {
|
|
4975
8214
|
<div
|
|
4976
8215
|
class="axm-post-questionnaire-content __summary ax-flex ax-flex-col ax-items-center ax-justify-center ax-p-8 ax-min-h-[200px] ax-text-on-surface"
|
|
@@ -4978,7 +8217,7 @@ class AXMPostQuestionnaireContentComponent {
|
|
|
4978
8217
|
<div class="ax-max-w-2xl ax-w-full ax-prose ax-text-on-surface" [innerHTML]="summaryContentHtml()"></div>
|
|
4979
8218
|
</div>
|
|
4980
8219
|
}
|
|
4981
|
-
`, isInline: true, styles: [".axm-post-questionnaire-content .__post-text-muted{color:rgb(var(--ax-sys-color-on-surface-variant))}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "ngmodule", type: AXPWidgetCoreModule }, { kind: "component", type: i1.AXPWidgetContainerComponent, selector: "axp-widgets-container", inputs: ["context", "functions"], outputs: ["onContextChanged"] }, { kind: "component", type: AXMQuestionnaireViewerQuestionComponent, selector: "axm-questionnaire-viewer-question", inputs: ["question", "contextData", "sectionOrder", "questionIndex", "showQuestionNumbers", "showQuestionCounter", "currentPosition", "mode"] }, { kind: "component", type: AXMQuestionnaireViewerSectionHeaderComponent, selector: "axm-questionnaire-viewer-section-header", inputs: ["title", "description", "titleSize", "marginBottom"] }, { kind: "pipe", type: i3.AsyncPipe, name: "async" }, { kind: "pipe", type: i4
|
|
8220
|
+
`, isInline: true, styles: [".axm-post-questionnaire-content .__post-text-muted{color:rgb(var(--ax-sys-color-on-surface-variant))}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "ngmodule", type: AXPWidgetCoreModule }, { kind: "component", type: i1$1.AXPWidgetContainerComponent, selector: "axp-widgets-container", inputs: ["context", "functions"], outputs: ["onContextChanged"] }, { kind: "component", type: AXMQuestionnaireOutcomeResultsComponent, selector: "axm-questionnaire-outcome-results", inputs: ["placeholderValues"] }, { kind: "component", type: AXMQuestionnaireViewerQuestionComponent, selector: "axm-questionnaire-viewer-question", inputs: ["question", "contextData", "sectionOrder", "questionIndex", "showQuestionNumbers", "showQuestionCounter", "currentPosition", "mode"] }, { kind: "component", type: AXMQuestionnaireViewerSectionHeaderComponent, selector: "axm-questionnaire-viewer-section-header", inputs: ["title", "description", "titleSize", "marginBottom"] }, { kind: "pipe", type: i3.AsyncPipe, name: "async" }, { kind: "pipe", type: i4.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
|
|
4982
8221
|
}
|
|
4983
8222
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMPostQuestionnaireContentComponent, decorators: [{
|
|
4984
8223
|
type: Component,
|
|
@@ -5056,43 +8295,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
|
|
|
5056
8295
|
</div>
|
|
5057
8296
|
</div>
|
|
5058
8297
|
} @else if (mode() === 'results') {
|
|
5059
|
-
<
|
|
5060
|
-
class="axm-post-questionnaire-content __results ax-flex ax-flex-col ax-items-center ax-justify-center ax-p-8 ax-min-h-[200px] ax-text-on-surface"
|
|
5061
|
-
>
|
|
5062
|
-
@if (outcomeEntries().length > 0) {
|
|
5063
|
-
<div class="ax-max-w-2xl ax-w-full">
|
|
5064
|
-
<h3 class="ax-text-base ax-font-semibold ax-mb-3 ax-text-on-surface">
|
|
5065
|
-
{{
|
|
5066
|
-
'@assessment-management:questionnaires.components.questionnaire-viewer.flow.outcomes-section-title'
|
|
5067
|
-
| translate
|
|
5068
|
-
| async
|
|
5069
|
-
}}
|
|
5070
|
-
</h3>
|
|
5071
|
-
<ul
|
|
5072
|
-
class="ax-list-none ax-p-0 ax-m-0 ax-flex ax-flex-col ax-gap-1 ax-rounded-lg ax-border ax-border-surface ax-lighter-surface ax-overflow-hidden"
|
|
5073
|
-
>
|
|
5074
|
-
@for (row of outcomeEntries(); track row.key) {
|
|
5075
|
-
<li
|
|
5076
|
-
class="ax-flex ax-justify-between ax-gap-4 ax-py-3 ax-px-4 ax-border-b ax-border-surface last:ax-border-b-0"
|
|
5077
|
-
>
|
|
5078
|
-
<span class="ax-text-sm ax-font-medium __post-text-muted">{{ row.label }}</span>
|
|
5079
|
-
<span class="ax-text-sm ax-text-on-surface ax-text-right ax-break-all">{{
|
|
5080
|
-
formatAnswer(row.value)
|
|
5081
|
-
}}</span>
|
|
5082
|
-
</li>
|
|
5083
|
-
}
|
|
5084
|
-
</ul>
|
|
5085
|
-
</div>
|
|
5086
|
-
} @else {
|
|
5087
|
-
<p class="ax-text-sm __post-text-muted">
|
|
5088
|
-
{{
|
|
5089
|
-
'@assessment-management:questionnaires.components.questionnaire-viewer.flow.no-outcomes'
|
|
5090
|
-
| translate
|
|
5091
|
-
| async
|
|
5092
|
-
}}
|
|
5093
|
-
</p>
|
|
5094
|
-
}
|
|
5095
|
-
</div>
|
|
8298
|
+
<axm-questionnaire-outcome-results [placeholderValues]="placeholderValues()" />
|
|
5096
8299
|
} @else {
|
|
5097
8300
|
<div
|
|
5098
8301
|
class="axm-post-questionnaire-content __summary ax-flex ax-flex-col ax-items-center ax-justify-center ax-p-8 ax-min-h-[200px] ax-text-on-surface"
|
|
@@ -5104,6 +8307,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
|
|
|
5104
8307
|
CommonModule,
|
|
5105
8308
|
AXTranslationModule,
|
|
5106
8309
|
AXPWidgetCoreModule,
|
|
8310
|
+
AXMQuestionnaireOutcomeResultsComponent,
|
|
5107
8311
|
AXMQuestionnaireViewerQuestionComponent,
|
|
5108
8312
|
AXMQuestionnaireViewerSectionHeaderComponent,
|
|
5109
8313
|
], encapsulation: ViewEncapsulation.None, host: { class: 'axm-post-questionnaire-content' }, styles: [".axm-post-questionnaire-content .__post-text-muted{color:rgb(var(--ax-sys-color-on-surface-variant))}\n"] }]
|
|
@@ -5133,6 +8337,7 @@ class AXMQuestionnaireViewerPageComponent extends AXPPageLayoutBaseComponent {
|
|
|
5133
8337
|
this.isLoading = signal(true, ...(ngDevMode ? [{ debugName: "isLoading" }] : /* istanbul ignore next */ []));
|
|
5134
8338
|
this.loadError = signal(null, ...(ngDevMode ? [{ debugName: "loadError" }] : /* istanbul ignore next */ []));
|
|
5135
8339
|
this.currentSessionId = signal(null, ...(ngDevMode ? [{ debugName: "currentSessionId" }] : /* istanbul ignore next */ []));
|
|
8340
|
+
this.existingSession = signal(null, ...(ngDevMode ? [{ debugName: "existingSession" }] : /* istanbul ignore next */ []));
|
|
5136
8341
|
this.flowStep = signal('questions', ...(ngDevMode ? [{ debugName: "flowStep" }] : /* istanbul ignore next */ []));
|
|
5137
8342
|
this.reviewSnapshot = signal([], ...(ngDevMode ? [{ debugName: "reviewSnapshot" }] : /* istanbul ignore next */ []));
|
|
5138
8343
|
this.reviewContext = signal(null, ...(ngDevMode ? [{ debugName: "reviewContext" }] : /* istanbul ignore next */ []));
|
|
@@ -5219,9 +8424,12 @@ class AXMQuestionnaireViewerPageComponent extends AXPPageLayoutBaseComponent {
|
|
|
5219
8424
|
.withEntity(RootConfig.module.name, RootConfig.entities.assessmentSession.name)
|
|
5220
8425
|
.data()
|
|
5221
8426
|
.byKey(existingSessionId);
|
|
5222
|
-
if (session
|
|
5223
|
-
|
|
8427
|
+
if (session) {
|
|
8428
|
+
if (session.answers) {
|
|
8429
|
+
answers = session.answers;
|
|
8430
|
+
}
|
|
5224
8431
|
this.currentSessionId.set(existingSessionId);
|
|
8432
|
+
this.existingSession.set(session);
|
|
5225
8433
|
}
|
|
5226
8434
|
}
|
|
5227
8435
|
this.questionnaire.set(questionnaire);
|
|
@@ -5253,7 +8461,7 @@ class AXMQuestionnaireViewerPageComponent extends AXPPageLayoutBaseComponent {
|
|
|
5253
8461
|
this.handleDone();
|
|
5254
8462
|
return;
|
|
5255
8463
|
}
|
|
5256
|
-
if (cfg?.post.
|
|
8464
|
+
if (cfg?.post.showOutcomeResults === true) {
|
|
5257
8465
|
this.flowStep.set('results');
|
|
5258
8466
|
return;
|
|
5259
8467
|
}
|
|
@@ -5269,7 +8477,6 @@ class AXMQuestionnaireViewerPageComponent extends AXPPageLayoutBaseComponent {
|
|
|
5269
8477
|
const q = this.questionnaire();
|
|
5270
8478
|
if (!caseIdVal || !structureVal || !q)
|
|
5271
8479
|
return null;
|
|
5272
|
-
const { answeredQuestionsCount, progressPercentage } = this.questionnaireViewerService.calculateProgressFromStructure(structureVal, answers);
|
|
5273
8480
|
const responderId = this.authSession.user?.id;
|
|
5274
8481
|
if (!responderId) {
|
|
5275
8482
|
this.toastService.show({
|
|
@@ -5279,39 +8486,41 @@ class AXMQuestionnaireViewerPageComponent extends AXPPageLayoutBaseComponent {
|
|
|
5279
8486
|
});
|
|
5280
8487
|
return null;
|
|
5281
8488
|
}
|
|
5282
|
-
const
|
|
5283
|
-
const
|
|
5284
|
-
|
|
5285
|
-
|
|
8489
|
+
const vm = this.viewerViewModel();
|
|
8490
|
+
const result = await persistAssessmentSession({
|
|
8491
|
+
entityService: this.entityService,
|
|
8492
|
+
questionnaireViewerService: this.questionnaireViewerService,
|
|
5286
8493
|
caseId: caseIdVal,
|
|
8494
|
+
sessionId: this.currentSessionId(),
|
|
8495
|
+
existingSession: this.existingSession(),
|
|
5287
8496
|
responderId,
|
|
5288
|
-
role,
|
|
8497
|
+
role: 'responder',
|
|
8498
|
+
structure: structureVal,
|
|
8499
|
+
questionnaireId: q.id,
|
|
5289
8500
|
answers,
|
|
5290
|
-
|
|
5291
|
-
|
|
5292
|
-
|
|
5293
|
-
|
|
5294
|
-
|
|
8501
|
+
finalize: true,
|
|
8502
|
+
progressMetrics: vm
|
|
8503
|
+
? {
|
|
8504
|
+
answeredQuestionsCount: vm.answeredQuestionsCount(),
|
|
8505
|
+
progressPercentage: vm.progressPercentage(),
|
|
8506
|
+
}
|
|
8507
|
+
: undefined,
|
|
8508
|
+
timeSpentSeconds: vm?.timerElapsed(),
|
|
8509
|
+
});
|
|
8510
|
+
this.currentSessionId.set(result.sessionId);
|
|
8511
|
+
const session = await this.entityService
|
|
5295
8512
|
.withEntity(RootConfig.module.name, RootConfig.entities.assessmentSession.name)
|
|
5296
|
-
.data()
|
|
5297
|
-
|
|
5298
|
-
|
|
5299
|
-
this.
|
|
5300
|
-
color: 'success',
|
|
5301
|
-
title: await this.translateService.translateAsync('@general:messages.form.saved.success.title'),
|
|
5302
|
-
content: await this.translateService.translateAsync('@general:messages.form.saved.success.description'),
|
|
5303
|
-
});
|
|
5304
|
-
}
|
|
5305
|
-
else {
|
|
5306
|
-
const newSessionData = { ...sessionData, startedAt: now };
|
|
5307
|
-
await sessionDataAccessor.create(newSessionData);
|
|
5308
|
-
this.toastService.show({
|
|
5309
|
-
color: 'success',
|
|
5310
|
-
title: await this.translateService.translateAsync('@assessment-management:sessions.states.submitted'),
|
|
5311
|
-
content: '',
|
|
5312
|
-
});
|
|
8513
|
+
.data()
|
|
8514
|
+
.byKey(result.sessionId);
|
|
8515
|
+
if (session) {
|
|
8516
|
+
this.existingSession.set(session);
|
|
5313
8517
|
}
|
|
5314
|
-
|
|
8518
|
+
this.toastService.show({
|
|
8519
|
+
color: 'success',
|
|
8520
|
+
title: await this.translateService.translateAsync('@assessment-management:sessions.states.submitted'),
|
|
8521
|
+
content: '',
|
|
8522
|
+
});
|
|
8523
|
+
const elapsed = vm?.timerElapsed() ?? 0;
|
|
5315
8524
|
return this.questionnaireViewerService.buildSummaryPlaceholderValues(structureVal, answers, {
|
|
5316
8525
|
questionnaireId: q.id,
|
|
5317
8526
|
elapsedSeconds: elapsed,
|
|
@@ -5405,9 +8614,9 @@ class AXMQuestionnaireViewerPageComponent extends AXPPageLayoutBaseComponent {
|
|
|
5405
8614
|
this.router.navigateByUrl(this.getCasesListPath());
|
|
5406
8615
|
}
|
|
5407
8616
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMQuestionnaireViewerPageComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
5408
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: AXMQuestionnaireViewerPageComponent, isStandalone: true, selector: "axm-questionnaire-viewer-page", host: { classAttribute: "axm-questionnaire-viewer-page" }, providers: [{ provide: AXPPageLayoutBase, useExisting: AXMQuestionnaireViewerPageComponent }], viewQueries: [{ propertyName: "viewer", first: true, predicate: ["viewer"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<!-- Page shell layout -->\n<axp-page-layout>\n <!-- Main content area -->\n <axp-page-content class=\"ax-flex ax-flex-col ax-flex-1 ax-min-h-0\"\n [class.ax-overflow-hidden]=\"flowStep() === 'questions'\" [class.ax-overflow-y-auto]=\"flowStep() !== 'questions'\">\n <!-- Loading state -->\n @if (isLoading()) {\n <div class=\"ax-flex ax-items-center ax-justify-center ax-min-h-[200px]\">\n <span>{{ '@assessment-management:questionnaires.components.questionnaire-viewer.loading.title' | translate | async\n }}</span>\n </div>\n }\n <!-- Error state -->\n @else if (loadError()) {\n <div class=\"ax-p-4 ax-text-error-600\">\n {{ loadError() }}\n </div>\n }\n <!-- Content state -->\n @else if (structure()) {\n <!-- Pre-questionnaire introduction content -->\n @if (flowStep() === 'pre') {\n <axm-pre-questionnaire-content [content]=\"prePostConfig()?.pre?.content\"></axm-pre-questionnaire-content>\n }\n <!-- Post-submit results content -->\n @else if (flowStep() === 'results') {\n <axm-post-questionnaire-content mode=\"results\"\n [placeholderValues]=\"submitResult()\"></axm-post-questionnaire-content>\n }\n <!-- Post-submit summary content -->\n @else if (flowStep() === 'summary') {\n <axm-post-questionnaire-content mode=\"summary\" [summaryContent]=\"prePostConfig()?.post?.summaryContent\"\n [placeholderValues]=\"submitResult()\"></axm-post-questionnaire-content>\n }\n <!-- Questionnaire and review flow -->\n @else {\n <!-- Review mode content -->\n @if (flowStep() === 'review') {\n <axm-post-questionnaire-content mode=\"review\" [questionsWithAnswers]=\"reviewSnapshot()\"\n [reviewContext]=\"reviewContext()\"></axm-post-questionnaire-content>\n }\n\n <!-- Questionnaire workspace (hidden while in review mode) -->\n <div class=\"__questions ax-flex ax-flex-col ax-flex-1 ax-min-h-0 ax-overflow-hidden\"\n [class.ax-invisible]=\"flowStep() === 'review'\" [style.position]=\"flowStep() === 'review' ? 'fixed' : null\"\n [style.left]=\"flowStep() === 'review' ? '-9999px' : null\" [class.ax-size-0]=\"flowStep() === 'review'\"\n [class.ax-overflow-hidden]=\"flowStep() === 'review'\">\n\n <!-- Questionnaire rendering container -->\n <div class=\"__content ax-flex ax-flex-col ax-flex-1 ax-min-h-0 ax-overflow-y-auto ax-overflow-x-hidden\">\n <axm-questionnaire-viewer #viewer [structure]=\"structure()!\" [config]=\"viewerConfig()\"\n [initialAnswers]=\"effectiveInitialAnswers()\"\n (answersChanged)=\"handleAnswersChanged($event)\"></axm-questionnaire-viewer>\n </div>\n </div>\n }\n }\n </axp-page-content>\n\n <!-- Footer actions (only when content is ready) -->\n @if (structure() && !isLoading() && !loadError()) {\n <axp-page-footer class=\"--animated\">\n <!-- Footer prefix: progress indicator -->\n <axp-layout-prefix>\n @if (flowStep() === 'questions') {\n <div class=\"__footer-progress ax-text-sm ax-font-mono ax-tabular-nums\" dir=\"ltr\">\n @if (showProgressBar()) {\n {{ answeredQuestionsCount() }} / {{ totalQuestionsCount() }}\n }\n </div>\n }\n <!-- @if (showTimer()) {\n <axp-stopwatch [mode]=\"timerTimeLimit() ? 'count-down' : 'count-up'\" [timeLimit]=\"timerTimeLimit()\"\n [format]=\"timerTimeLimit() && timerTimeLimit()! >= 3600 ? 'hh:mm:ss' : 'mm:ss'\" [autoStart]=\"true\"\n [showControls]=\"false\" [value]=\"timerElapsed()\"\n (valueChange)=\"viewerViewModel()!.updateTimerElapsed($event)\"></axp-stopwatch>\n } -->\n </axp-layout-prefix>\n\n <!-- Footer suffix: flow action buttons -->\n <axp-layout-suffix>\n @if (flowStep() === 'pre') {\n <ax-button look=\"solid\" color=\"primary\"\n [text]=\"'@assessment-management:questionnaires.components.questionnaire-viewer.flow.start' | translate | async\"\n (onClick)=\"flowStep.set('questions')\"></ax-button>\n }\n <!-- Question step actions -->\n @else if (flowStep() === 'questions') {\n <!-- Question navigation buttons -->\n @if (showNavigationButtons()) {\n <ax-button look=\"solid\" [disabled]=\"!canNavigatePrevious()\"\n [text]=\"'@general:actions.previous.title' | translate | async\" (onClick)=\"handlePreviousClick()\"></ax-button>\n @if (!isLastStep()) {\n <ax-button look=\"solid\" color=\"primary\" [disabled]=\"!canNavigateNext()\"\n [text]=\"'@general:actions.next.title' | translate | async\" (onClick)=\"handleNextClick()\"></ax-button>\n }\n }\n\n <!-- Final-step actions -->\n @if (isLastStep() && showReviewButton()) {\n <ax-button look=\"solid\" color=\"primary\"\n [text]=\"'@assessment-management:questionnaires.components.questionnaire-viewer.flow.review' | translate | async\"\n [disabled]=\"!areAllRequiredQuestionsAnswered()\" (onClick)=\"handleReviewClick()\"></ax-button>\n }\n @if (isLastStep() && !showReviewButton()) {\n <ax-button look=\"solid\" color=\"primary\" [text]=\"'@general:actions.submit.title' | translate | async\"\n [disabled]=\"isReadonly() || isSubmitting() || !areAllRequiredQuestionsAnswered()\"\n (onClick)=\"handleSubmitClick()\"></ax-button>\n }\n }\n <!-- Review step actions -->\n @else if (flowStep() === 'review') {\n <ax-button look=\"outline\"\n [text]=\"'@assessment-management:questionnaires.components.questionnaire-viewer.flow.edit' | translate | async\"\n (onClick)=\"flowStep.set('questions')\"></ax-button>\n <ax-button look=\"solid\" color=\"primary\" [text]=\"'@general:actions.submit.title' | translate | async\"\n [disabled]=\"isSubmitting()\" (onClick)=\"handleReviewSubmit()\"></ax-button>\n }\n <!-- Results step actions -->\n @else if (flowStep() === 'results') {\n @if (prePostConfig()?.post?.summaryEnabled) {\n <ax-button look=\"solid\" color=\"primary\" [text]=\"'@general:actions.next.title' | translate | async\"\n (onClick)=\"flowStep.set('summary')\"></ax-button>\n } @else {\n <ax-button look=\"solid\" color=\"primary\"\n [text]=\"'@assessment-management:questionnaires.components.questionnaire-viewer.flow.done' | translate | async\"\n (onClick)=\"handleDone()\"></ax-button>\n }\n }\n <!-- Summary step action -->\n @else if (flowStep() === 'summary') {\n <ax-button look=\"solid\" color=\"primary\"\n [text]=\"'@assessment-management:questionnaires.components.questionnaire-viewer.flow.done' | translate | async\"\n (onClick)=\"handleDone()\"></ax-button>\n }\n </axp-layout-suffix>\n </axp-page-footer>\n }\n</axp-page-layout>", styles: ["axm-questionnaire-viewer-page .__questions{min-height:0px;overflow:hidden}axm-questionnaire-viewer-page .__header{z-index:20;display:flex;flex-shrink:0;flex-direction:column;background-color:rgb(var(--ax-sys-color-lightest-surface));color:rgb(var(--ax-sys-color-on-lightest-surface));border-color:rgb(var(--ax-sys-color-border-lightest-surface));border-bottom-width:1px;--tw-border-opacity: 1;border-color:rgba(var(--ax-sys-color-border-surface),var(--tw-border-opacity, 1));position:sticky;top:0;color:rgb(var(--ax-sys-color-on-surface-variant))}axm-questionnaire-viewer-page .__content axm-questionnaire-viewer{display:flex;height:auto;max-height:none;min-height:0px;width:100%;max-width:100%;flex:none;flex-direction:column}axm-questionnaire-viewer-page .__content axm-questionnaire-viewer .__questionnaire-container{min-height:0px;flex:none;overflow:visible}axm-questionnaire-viewer-page .__toolbar-meta{color:rgb(var(--ax-sys-color-on-surface-variant))}axm-questionnaire-viewer-page .__footer-progress{color:rgb(var(--ax-sys-color-on-surface-variant))}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i1
|
|
8617
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: AXMQuestionnaireViewerPageComponent, isStandalone: true, selector: "axm-questionnaire-viewer-page", host: { classAttribute: "axm-questionnaire-viewer-page" }, providers: [{ provide: AXPPageLayoutBase, useExisting: AXMQuestionnaireViewerPageComponent }], viewQueries: [{ propertyName: "viewer", first: true, predicate: ["viewer"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<!-- Page shell layout -->\n<axp-page-layout>\n <!-- Main content area -->\n <axp-page-content class=\"ax-flex ax-flex-col ax-flex-1 ax-min-h-0\"\n [class.ax-overflow-hidden]=\"flowStep() === 'questions'\" [class.ax-overflow-y-auto]=\"flowStep() !== 'questions'\">\n <!-- Loading state -->\n @if (isLoading()) {\n <div class=\"ax-flex ax-items-center ax-justify-center ax-min-h-[200px]\">\n <span>{{ '@assessment-management:questionnaires.components.questionnaire-viewer.loading.title' | translate | async\n }}</span>\n </div>\n }\n <!-- Error state -->\n @else if (loadError()) {\n <div class=\"ax-p-4 ax-text-error-600\">\n {{ loadError() }}\n </div>\n }\n <!-- Content state -->\n @else if (structure()) {\n <!-- Pre-questionnaire introduction content -->\n @if (flowStep() === 'pre') {\n <axm-pre-questionnaire-content [content]=\"prePostConfig()?.pre?.content\"></axm-pre-questionnaire-content>\n }\n <!-- Post-submit results content -->\n @else if (flowStep() === 'results') {\n <axm-post-questionnaire-content mode=\"results\"\n [placeholderValues]=\"submitResult()\"></axm-post-questionnaire-content>\n }\n <!-- Post-submit summary content -->\n @else if (flowStep() === 'summary') {\n <axm-post-questionnaire-content mode=\"summary\" [summaryContent]=\"prePostConfig()?.post?.summaryContent\"\n [placeholderValues]=\"submitResult()\"></axm-post-questionnaire-content>\n }\n <!-- Questionnaire and review flow -->\n @else {\n <!-- Review mode content -->\n @if (flowStep() === 'review') {\n <axm-post-questionnaire-content mode=\"review\" [questionsWithAnswers]=\"reviewSnapshot()\"\n [reviewContext]=\"reviewContext()\"></axm-post-questionnaire-content>\n }\n\n <!-- Questionnaire workspace (hidden while in review mode) -->\n <div class=\"__questions ax-flex ax-flex-col ax-flex-1 ax-min-h-0 ax-overflow-hidden\"\n [class.ax-invisible]=\"flowStep() === 'review'\" [style.position]=\"flowStep() === 'review' ? 'fixed' : null\"\n [style.left]=\"flowStep() === 'review' ? '-9999px' : null\" [class.ax-size-0]=\"flowStep() === 'review'\"\n [class.ax-overflow-hidden]=\"flowStep() === 'review'\">\n\n <!-- Questionnaire rendering container -->\n <div class=\"__content ax-flex ax-flex-col ax-flex-1 ax-min-h-0 ax-overflow-y-auto ax-overflow-x-hidden\">\n <axm-questionnaire-viewer #viewer [structure]=\"structure()!\" [config]=\"viewerConfig()\"\n [initialAnswers]=\"effectiveInitialAnswers()\"\n (answersChanged)=\"handleAnswersChanged($event)\"></axm-questionnaire-viewer>\n </div>\n </div>\n }\n }\n </axp-page-content>\n\n <!-- Footer actions (only when content is ready) -->\n @if (structure() && !isLoading() && !loadError()) {\n <axp-page-footer class=\"--animated\">\n <!-- Footer prefix: progress indicator -->\n <axp-layout-prefix>\n @if (flowStep() === 'questions') {\n <div class=\"__footer-progress ax-text-sm ax-font-mono ax-tabular-nums\" dir=\"ltr\">\n @if (showProgressBar()) {\n {{ answeredQuestionsCount() }} / {{ totalQuestionsCount() }}\n }\n </div>\n }\n <!-- @if (showTimer()) {\n <axp-stopwatch [mode]=\"timerTimeLimit() ? 'count-down' : 'count-up'\" [timeLimit]=\"timerTimeLimit()\"\n [format]=\"timerTimeLimit() && timerTimeLimit()! >= 3600 ? 'hh:mm:ss' : 'mm:ss'\" [autoStart]=\"true\"\n [showControls]=\"false\" [value]=\"timerElapsed()\"\n (valueChange)=\"viewerViewModel()!.updateTimerElapsed($event)\"></axp-stopwatch>\n } -->\n </axp-layout-prefix>\n\n <!-- Footer suffix: flow action buttons -->\n <axp-layout-suffix>\n @if (flowStep() === 'pre') {\n <ax-button look=\"solid\" color=\"primary\"\n [text]=\"'@assessment-management:questionnaires.components.questionnaire-viewer.flow.start' | translate | async\"\n (onClick)=\"flowStep.set('questions')\"></ax-button>\n }\n <!-- Question step actions -->\n @else if (flowStep() === 'questions') {\n <!-- Question navigation buttons -->\n @if (showNavigationButtons()) {\n <ax-button look=\"solid\" [disabled]=\"!canNavigatePrevious()\"\n [text]=\"'@general:actions.previous.title' | translate | async\" (onClick)=\"handlePreviousClick()\"></ax-button>\n @if (!isLastStep()) {\n <ax-button look=\"solid\" color=\"primary\" [disabled]=\"!canNavigateNext()\"\n [text]=\"'@general:actions.next.title' | translate | async\" (onClick)=\"handleNextClick()\"></ax-button>\n }\n }\n\n <!-- Final-step actions -->\n @if (isLastStep() && showReviewButton()) {\n <ax-button look=\"solid\" color=\"primary\"\n [text]=\"'@assessment-management:questionnaires.components.questionnaire-viewer.flow.review' | translate | async\"\n [disabled]=\"!areAllRequiredQuestionsAnswered()\" (onClick)=\"handleReviewClick()\"></ax-button>\n }\n @if (isLastStep() && !showReviewButton()) {\n <ax-button look=\"solid\" color=\"primary\" [text]=\"'@general:actions.submit.title' | translate | async\"\n [disabled]=\"isReadonly() || isSubmitting() || !areAllRequiredQuestionsAnswered()\"\n (onClick)=\"handleSubmitClick()\"></ax-button>\n }\n }\n <!-- Review step actions -->\n @else if (flowStep() === 'review') {\n <ax-button look=\"outline\"\n [text]=\"'@assessment-management:questionnaires.components.questionnaire-viewer.flow.edit' | translate | async\"\n (onClick)=\"flowStep.set('questions')\"></ax-button>\n <ax-button look=\"solid\" color=\"primary\" [text]=\"'@general:actions.submit.title' | translate | async\"\n [disabled]=\"isSubmitting()\" (onClick)=\"handleReviewSubmit()\"></ax-button>\n }\n <!-- Results step actions -->\n @else if (flowStep() === 'results') {\n @if (prePostConfig()?.post?.summaryEnabled) {\n <ax-button look=\"solid\" color=\"primary\" [text]=\"'@general:actions.next.title' | translate | async\"\n (onClick)=\"flowStep.set('summary')\"></ax-button>\n } @else {\n <ax-button look=\"solid\" color=\"primary\"\n [text]=\"'@assessment-management:questionnaires.components.questionnaire-viewer.flow.done' | translate | async\"\n (onClick)=\"handleDone()\"></ax-button>\n }\n }\n <!-- Summary step action -->\n @else if (flowStep() === 'summary') {\n <ax-button look=\"solid\" color=\"primary\"\n [text]=\"'@assessment-management:questionnaires.components.questionnaire-viewer.flow.done' | translate | async\"\n (onClick)=\"handleDone()\"></ax-button>\n }\n </axp-layout-suffix>\n </axp-page-footer>\n }\n</axp-page-layout>", styles: ["axm-questionnaire-viewer-page .__questions{min-height:0px;overflow:hidden}axm-questionnaire-viewer-page .__header{z-index:20;display:flex;flex-shrink:0;flex-direction:column;background-color:rgb(var(--ax-sys-color-lightest-surface));color:rgb(var(--ax-sys-color-on-lightest-surface));border-color:rgb(var(--ax-sys-color-border-lightest-surface));border-bottom-width:1px;--tw-border-opacity: 1;border-color:rgba(var(--ax-sys-color-border-surface),var(--tw-border-opacity, 1));position:sticky;top:0;color:rgb(var(--ax-sys-color-on-surface-variant))}axm-questionnaire-viewer-page .__content axm-questionnaire-viewer{display:flex;height:auto;max-height:none;min-height:0px;width:100%;max-width:100%;flex:none;flex-direction:column}axm-questionnaire-viewer-page .__content axm-questionnaire-viewer .__questionnaire-container{min-height:0px;flex:none;overflow:visible}axm-questionnaire-viewer-page .__toolbar-meta{color:rgb(var(--ax-sys-color-on-surface-variant))}axm-questionnaire-viewer-page .__footer-progress{color:rgb(var(--ax-sys-color-on-surface-variant))}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i1.AXButtonComponent, selector: "ax-button", inputs: ["disabled", "size", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "component", type: AXPPageLayoutComponent, selector: "axp-page-layout" }, { kind: "component", type: AXPThemeLayoutBlockComponent, selector: " axp-page-content, axp-page-footer-container, axp-page-footer, axp-page-header, axp-page-header-container, axp-page-toolbar, axp-layout-content, axp-layout-page-content, axp-layout-sections, axp-layout-body, axp-layout-page-body, axp-layout-prefix, axp-layout-suffix, axp-layout-title-bar, axp-layout-title, axp-layout-title-actions, axp-layout-nav-button, axp-layout-description, axp-layout-breadcrumbs, axp-layout-list-action, " }, { kind: "component", type:
|
|
5409
8618
|
//AXPStopwatchComponent,
|
|
5410
|
-
AXMQuestionnaireViewerComponent, selector: "axm-questionnaire-viewer", inputs: ["questionnaireId", "structure", "config", "initialAnswers"], outputs: ["answersChanged", "questionAnswered"] }, { kind: "component", type: AXMPreQuestionnaireContentComponent, selector: "axm-pre-questionnaire-content", inputs: ["content"] }, { kind: "component", type: AXMPostQuestionnaireContentComponent, selector: "axm-post-questionnaire-content", inputs: ["mode", "questionsWithAnswers", "reviewContext", "summaryContent", "placeholderValues", "locale", "showQuestionNumbers"] }, { kind: "pipe", type: i3.AsyncPipe, name: "async" }, { kind: "pipe", type: i4
|
|
8619
|
+
AXMQuestionnaireViewerComponent, selector: "axm-questionnaire-viewer", inputs: ["questionnaireId", "structure", "config", "initialAnswers"], outputs: ["answersChanged", "questionAnswered"] }, { kind: "component", type: AXMPreQuestionnaireContentComponent, selector: "axm-pre-questionnaire-content", inputs: ["content"] }, { kind: "component", type: AXMPostQuestionnaireContentComponent, selector: "axm-post-questionnaire-content", inputs: ["mode", "questionsWithAnswers", "reviewContext", "summaryContent", "placeholderValues", "locale", "showQuestionNumbers"] }, { kind: "pipe", type: i3.AsyncPipe, name: "async" }, { kind: "pipe", type: i4.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
|
|
5411
8620
|
}
|
|
5412
8621
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMQuestionnaireViewerPageComponent, decorators: [{
|
|
5413
8622
|
type: Component,
|
|
@@ -5450,6 +8659,8 @@ class AXMQuestionnaireViewerStandalonePageComponent {
|
|
|
5450
8659
|
this.isLoading = signal(true, ...(ngDevMode ? [{ debugName: "isLoading" }] : /* istanbul ignore next */ []));
|
|
5451
8660
|
this.loadError = signal(null, ...(ngDevMode ? [{ debugName: "loadError" }] : /* istanbul ignore next */ []));
|
|
5452
8661
|
this.isSubmitting = signal(false, ...(ngDevMode ? [{ debugName: "isSubmitting" }] : /* istanbul ignore next */ []));
|
|
8662
|
+
this.sessionId = signal(null, ...(ngDevMode ? [{ debugName: "sessionId" }] : /* istanbul ignore next */ []));
|
|
8663
|
+
this.existingSession = signal(null, ...(ngDevMode ? [{ debugName: "existingSession" }] : /* istanbul ignore next */ []));
|
|
5453
8664
|
this.flowStep = signal('questions', ...(ngDevMode ? [{ debugName: "flowStep" }] : /* istanbul ignore next */ []));
|
|
5454
8665
|
this.reviewSnapshot = signal([], ...(ngDevMode ? [{ debugName: "reviewSnapshot" }] : /* istanbul ignore next */ []));
|
|
5455
8666
|
this.reviewContext = signal(null, ...(ngDevMode ? [{ debugName: "reviewContext" }] : /* istanbul ignore next */ []));
|
|
@@ -5517,6 +8728,8 @@ class AXMQuestionnaireViewerStandalonePageComponent {
|
|
|
5517
8728
|
this.isLoading.set(false);
|
|
5518
8729
|
return;
|
|
5519
8730
|
}
|
|
8731
|
+
this.sessionId.set(sessionId);
|
|
8732
|
+
this.existingSession.set(session);
|
|
5520
8733
|
const caseId = session.caseId;
|
|
5521
8734
|
const assessmentCase = await this.entityService
|
|
5522
8735
|
.withEntity(RootConfig.module.name, RootConfig.entities.assessmentCase.name)
|
|
@@ -5558,28 +8771,41 @@ class AXMQuestionnaireViewerStandalonePageComponent {
|
|
|
5558
8771
|
//#endregion
|
|
5559
8772
|
//#region ---- Submit Handler ----
|
|
5560
8773
|
async saveSessionAndGetSummary(answers) {
|
|
5561
|
-
const
|
|
8774
|
+
const sessionIdVal = this.sessionId();
|
|
5562
8775
|
const structureVal = this.structure();
|
|
5563
8776
|
const q = this.questionnaire();
|
|
5564
|
-
|
|
8777
|
+
const session = this.existingSession();
|
|
8778
|
+
if (!sessionIdVal || !structureVal || !q || !session)
|
|
5565
8779
|
return null;
|
|
5566
|
-
const
|
|
5567
|
-
const
|
|
8780
|
+
const vm = this.viewerViewModel();
|
|
8781
|
+
const result = await persistAssessmentSession({
|
|
8782
|
+
entityService: this.entityService,
|
|
8783
|
+
questionnaireViewerService: this.questionnaireViewerService,
|
|
8784
|
+
caseId: session.caseId,
|
|
8785
|
+
sessionId: sessionIdVal,
|
|
8786
|
+
existingSession: session,
|
|
8787
|
+
responderId: session.responderId,
|
|
8788
|
+
role: session.role,
|
|
8789
|
+
structure: structureVal,
|
|
8790
|
+
questionnaireId: q.id,
|
|
8791
|
+
answers,
|
|
8792
|
+
finalize: true,
|
|
8793
|
+
progressMetrics: vm
|
|
8794
|
+
? {
|
|
8795
|
+
answeredQuestionsCount: vm.answeredQuestionsCount(),
|
|
8796
|
+
progressPercentage: vm.progressPercentage(),
|
|
8797
|
+
}
|
|
8798
|
+
: undefined,
|
|
8799
|
+
timeSpentSeconds: vm?.timerElapsed(),
|
|
8800
|
+
});
|
|
8801
|
+
const updated = await this.entityService
|
|
5568
8802
|
.withEntity(RootConfig.module.name, RootConfig.entities.assessmentSession.name)
|
|
5569
8803
|
.data()
|
|
5570
|
-
.byKey(sessionId);
|
|
5571
|
-
if (
|
|
5572
|
-
|
|
5573
|
-
.withEntity(RootConfig.module.name, RootConfig.entities.assessmentSession.name)
|
|
5574
|
-
.data()
|
|
5575
|
-
.update(sessionId, {
|
|
5576
|
-
answers,
|
|
5577
|
-
progressPercentage,
|
|
5578
|
-
answeredQuestionsCount,
|
|
5579
|
-
lastSavedAt: new Date(),
|
|
5580
|
-
});
|
|
8804
|
+
.byKey(result.sessionId);
|
|
8805
|
+
if (updated) {
|
|
8806
|
+
this.existingSession.set(updated);
|
|
5581
8807
|
}
|
|
5582
|
-
const elapsed =
|
|
8808
|
+
const elapsed = vm?.timerElapsed() ?? 0;
|
|
5583
8809
|
return this.questionnaireViewerService.buildSummaryPlaceholderValues(structureVal, answers, {
|
|
5584
8810
|
questionnaireId: q.id,
|
|
5585
8811
|
elapsedSeconds: elapsed,
|
|
@@ -5594,7 +8820,7 @@ class AXMQuestionnaireViewerStandalonePageComponent {
|
|
|
5594
8820
|
this.handleDone();
|
|
5595
8821
|
return;
|
|
5596
8822
|
}
|
|
5597
|
-
if (cfg?.post.
|
|
8823
|
+
if (cfg?.post.showOutcomeResults === true) {
|
|
5598
8824
|
this.flowStep.set('results');
|
|
5599
8825
|
return;
|
|
5600
8826
|
}
|
|
@@ -5783,7 +9009,7 @@ class AXMQuestionnaireViewerStandalonePageComponent {
|
|
|
5783
9009
|
</ax-footer>
|
|
5784
9010
|
}
|
|
5785
9011
|
</div>
|
|
5786
|
-
`, isInline: true, styles: ["axm-questionnaire-viewer-standalone-page{display:flex;min-height:0px;width:100%;flex:1 1 0%;flex-direction:column;overflow:hidden}axm-questionnaire-viewer-standalone-page .__body{display:flex;min-height:0px;width:100%;flex:1 1 0%;flex-direction:column;overflow:hidden}axm-questionnaire-viewer-standalone-page .__content-area{min-height:0px;overflow:hidden}axm-questionnaire-viewer-standalone-page .__questions{min-height:0px;overflow:hidden}axm-questionnaire-viewer-standalone-page .__header{z-index:20;display:flex;flex-shrink:0;flex-direction:column;background-color:rgb(var(--ax-sys-color-lightest-surface));color:rgb(var(--ax-sys-color-on-lightest-surface));border-color:rgb(var(--ax-sys-color-border-lightest-surface));border-bottom-width:1px;--tw-border-opacity: 1;border-color:rgba(var(--ax-sys-color-border-surface),var(--tw-border-opacity, 1));color:rgb(var(--ax-sys-color-on-surface-variant));position:sticky;top:0}axm-questionnaire-viewer-standalone-page .__header .__header-top{display:flex;align-items:center;justify-content:space-between;gap:1rem;padding:.75rem 1rem}axm-questionnaire-viewer-standalone-page .__header .__header-top .__header-meta{display:flex;align-items:center;gap:1rem;font-size:.75rem;line-height:1rem;--tw-text-opacity: 1;color:rgb(82 82 82 / var(--tw-text-opacity, 1))}axm-questionnaire-viewer-standalone-page .__header .__header-top .__header-meta .__meta-item{display:flex;align-items:center;gap:.375rem}axm-questionnaire-viewer-standalone-page .__header .__header-top .__header-meta .__meta-item i{font-size:.875rem;line-height:1.25rem;--tw-text-opacity: 1;color:rgba(var(--ax-sys-color-primary-600),var(--tw-text-opacity, 1))}axm-questionnaire-viewer-standalone-page .__header .__header-top .__header-meta .__meta-item span{font-weight:500}axm-questionnaire-viewer-standalone-page .__header .__header-top .__header-timer{display:flex;flex-shrink:0;align-items:center}axm-questionnaire-viewer-standalone-page .__content-wrapper{display:flex;min-height:0px;flex:1 1 0%;overflow:hidden}axm-questionnaire-viewer-standalone-page .__content axm-questionnaire-viewer{display:flex;height:auto;max-height:none;min-height:0px;width:100%;max-width:100%;flex:none;flex-direction:column}axm-questionnaire-viewer-standalone-page .__content axm-questionnaire-viewer .__questionnaire-container{min-height:0px;flex:none;overflow:visible}axm-questionnaire-viewer-standalone-page .__toolbar-meta{color:rgb(var(--ax-sys-color-on-surface-variant))}axm-questionnaire-viewer-standalone-page .__footer-progress{color:rgb(var(--ax-sys-color-on-surface-variant))}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i1
|
|
9012
|
+
`, isInline: true, styles: ["axm-questionnaire-viewer-standalone-page{display:flex;min-height:0px;width:100%;flex:1 1 0%;flex-direction:column;overflow:hidden}axm-questionnaire-viewer-standalone-page .__body{display:flex;min-height:0px;width:100%;flex:1 1 0%;flex-direction:column;overflow:hidden}axm-questionnaire-viewer-standalone-page .__content-area{min-height:0px;overflow:hidden}axm-questionnaire-viewer-standalone-page .__questions{min-height:0px;overflow:hidden}axm-questionnaire-viewer-standalone-page .__header{z-index:20;display:flex;flex-shrink:0;flex-direction:column;background-color:rgb(var(--ax-sys-color-lightest-surface));color:rgb(var(--ax-sys-color-on-lightest-surface));border-color:rgb(var(--ax-sys-color-border-lightest-surface));border-bottom-width:1px;--tw-border-opacity: 1;border-color:rgba(var(--ax-sys-color-border-surface),var(--tw-border-opacity, 1));color:rgb(var(--ax-sys-color-on-surface-variant));position:sticky;top:0}axm-questionnaire-viewer-standalone-page .__header .__header-top{display:flex;align-items:center;justify-content:space-between;gap:1rem;padding:.75rem 1rem}axm-questionnaire-viewer-standalone-page .__header .__header-top .__header-meta{display:flex;align-items:center;gap:1rem;font-size:.75rem;line-height:1rem;--tw-text-opacity: 1;color:rgb(82 82 82 / var(--tw-text-opacity, 1))}axm-questionnaire-viewer-standalone-page .__header .__header-top .__header-meta .__meta-item{display:flex;align-items:center;gap:.375rem}axm-questionnaire-viewer-standalone-page .__header .__header-top .__header-meta .__meta-item i{font-size:.875rem;line-height:1.25rem;--tw-text-opacity: 1;color:rgba(var(--ax-sys-color-primary-600),var(--tw-text-opacity, 1))}axm-questionnaire-viewer-standalone-page .__header .__header-top .__header-meta .__meta-item span{font-weight:500}axm-questionnaire-viewer-standalone-page .__header .__header-top .__header-timer{display:flex;flex-shrink:0;align-items:center}axm-questionnaire-viewer-standalone-page .__content-wrapper{display:flex;min-height:0px;flex:1 1 0%;overflow:hidden}axm-questionnaire-viewer-standalone-page .__content axm-questionnaire-viewer{display:flex;height:auto;max-height:none;min-height:0px;width:100%;max-width:100%;flex:none;flex-direction:column}axm-questionnaire-viewer-standalone-page .__content axm-questionnaire-viewer .__questionnaire-container{min-height:0px;flex:none;overflow:visible}axm-questionnaire-viewer-standalone-page .__toolbar-meta{color:rgb(var(--ax-sys-color-on-surface-variant))}axm-questionnaire-viewer-standalone-page .__footer-progress{color:rgb(var(--ax-sys-color-on-surface-variant))}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i1.AXButtonComponent, selector: "ax-button", inputs: ["disabled", "size", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i2.AXDecoratorGenericComponent, selector: "ax-footer, ax-header, ax-content, ax-divider, ax-form-hint, ax-prefix, ax-suffix, ax-text, ax-title, ax-subtitle, ax-placeholder, ax-overlay" }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "ngmodule", type: AXPWidgetCoreModule }, { kind: "component", type: AXPStopwatchComponent, selector: "axp-stopwatch", inputs: ["mode", "timeLimit", "format", "autoStart", "showControls", "value"], outputs: ["valueChange", "timeUp"] }, { kind: "component", type: AXMQuestionnaireViewerComponent, selector: "axm-questionnaire-viewer", inputs: ["questionnaireId", "structure", "config", "initialAnswers"], outputs: ["answersChanged", "questionAnswered"] }, { kind: "component", type: AXMPreQuestionnaireContentComponent, selector: "axm-pre-questionnaire-content", inputs: ["content"] }, { kind: "component", type: AXMPostQuestionnaireContentComponent, selector: "axm-post-questionnaire-content", inputs: ["mode", "questionsWithAnswers", "reviewContext", "summaryContent", "placeholderValues", "locale", "showQuestionNumbers"] }, { kind: "pipe", type: i3.AsyncPipe, name: "async" }, { kind: "pipe", type: i4.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
|
|
5787
9013
|
}
|
|
5788
9014
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMQuestionnaireViewerStandalonePageComponent, decorators: [{
|
|
5789
9015
|
type: Component,
|
|
@@ -5920,5 +9146,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
|
|
|
5920
9146
|
* Generated bundle index. Do not edit.
|
|
5921
9147
|
*/
|
|
5922
9148
|
|
|
5923
|
-
export { AXMQuestionnaireViewerService as A,
|
|
5924
|
-
//# sourceMappingURL=acorex-modules-assessment-management-acorex-modules-assessment-management-
|
|
9149
|
+
export { AXMQuestionnaireViewerService as A, diffQuestionCommentOverride as B, diffQuestionHintOverride as C, DEFAULT_POST_QUESTIONNAIRE_CONFIG as D, findDuplicateOutcomeNames as E, flattenQuestionnaireOutcomeItems as F, getQuestionAnswerCommentStoragePath as G, isQuestionnaireOutcomeDisplayColorHex as H, matchesQuestionnaireOutcomeDisplayRule as I, mergeQuestionCommentConfig as J, mergeQuestionHintForViewer as K, normalizeQuestionCommentConfig as L, normalizeQuestionHintConfig as M, normalizeQuestionHintFromEntityRow as N, normalizeQuestionHintMode as O, normalizeQuestionnaireOutcomeDisplayRules as P, QUESTIONNAIRE_QUESTIONS_PAGE_COMPONENT_KEY as Q, RootConfig as R, normalizeQuestionnaireOutcomesValue as S, normalizeValidationStrategy$1 as T, normalizeViewMode as U, parseQuestionHintPartialFromRecord as V, parseQuestionnaireOutcomeDisplayColor as W, readHintFieldsFromRecord as X, QUESTIONNAIRE_OUTCOMES_PAGE_COMPONENT_KEY as a, AXMQuestionnaireViewerComponent as b, AXMPreQuestionnaireContentComponent as c, AXMPostQuestionnaireContentComponent as d, toDisplaySettings as e, AXMAssessmentManagementEntityProvider as f, AXMAssessmentManagementFeatureDefinitionProvider as g, AXMAssessmentManagementFeatureKeys as h, AXMAssessmentManagementMenuProvider as i, AXMAssessmentManagementModule as j, AXMAssessmentManagementPermissionDefinitionProvider as k, AXMAssessmentManagementPermissionKeys as l, AXMAssessmentManagementSearchCommandProvider as m, normalizeCompletionMode as n, AXMQuestionnaireViewerPageComponent as o, persistAssessmentSession as p, AXMQuestionnaireViewerStandalonePageComponent as q, resolveWidgetNodeFromMetaDataDefinitionInterface as r, stripQuestionBankInterfaceMetadata as s, toPrePostConfig as t, AXPAssessmentManagementMenuKeys as u, DEFAULT_PRE_QUESTIONNAIRE_CONFIG as v, DEFAULT_QUESTIONNAIRE_ENTITY_DISPLAY as w, DEFAULT_QUESTIONNAIRE_OUTCOMES as x, DEFAULT_QUESTION_COMMENT_CONFIG as y, DEFAULT_QUESTION_HINT_CONFIG as z };
|
|
9150
|
+
//# sourceMappingURL=acorex-modules-assessment-management-acorex-modules-assessment-management-DqmJVJ0z.mjs.map
|