@mj-biz-apps/forms-ng 0.0.0 → 0.2.0
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/dist/lib/builder/builder-models.d.ts +27 -0
- package/dist/lib/builder/builder-models.d.ts.map +1 -0
- package/dist/lib/builder/builder-models.js +15 -0
- package/dist/lib/builder/builder-models.js.map +1 -0
- package/dist/lib/builder/builder-state.service.d.ts +48 -0
- package/dist/lib/builder/builder-state.service.d.ts.map +1 -0
- package/dist/lib/builder/builder-state.service.js +231 -0
- package/dist/lib/builder/builder-state.service.js.map +1 -0
- package/dist/lib/builder/builder-styles.d.ts +12 -0
- package/dist/lib/builder/builder-styles.d.ts.map +1 -0
- package/dist/lib/builder/builder-styles.js +74 -0
- package/dist/lib/builder/builder-styles.js.map +1 -0
- package/dist/lib/builder/conditional-rule-editor.component.d.ts +53 -0
- package/dist/lib/builder/conditional-rule-editor.component.d.ts.map +1 -0
- package/dist/lib/builder/conditional-rule-editor.component.js +282 -0
- package/dist/lib/builder/conditional-rule-editor.component.js.map +1 -0
- package/dist/lib/builder/design-panel.component.d.ts +71 -0
- package/dist/lib/builder/design-panel.component.d.ts.map +1 -0
- package/dist/lib/builder/design-panel.component.js +530 -0
- package/dist/lib/builder/design-panel.component.js.map +1 -0
- package/dist/lib/builder/design-panel.styles.d.ts +10 -0
- package/dist/lib/builder/design-panel.styles.d.ts.map +1 -0
- package/dist/lib/builder/design-panel.styles.js +78 -0
- package/dist/lib/builder/design-panel.styles.js.map +1 -0
- package/dist/lib/builder/design-state.service.d.ts +51 -0
- package/dist/lib/builder/design-state.service.d.ts.map +1 -0
- package/dist/lib/builder/design-state.service.js +108 -0
- package/dist/lib/builder/design-state.service.js.map +1 -0
- package/dist/lib/builder/distribution-links.d.ts +29 -0
- package/dist/lib/builder/distribution-links.d.ts.map +1 -0
- package/dist/lib/builder/distribution-links.js +53 -0
- package/dist/lib/builder/distribution-links.js.map +1 -0
- package/dist/lib/builder/distribution-manager.component.d.ts +53 -0
- package/dist/lib/builder/distribution-manager.component.d.ts.map +1 -0
- package/dist/lib/builder/distribution-manager.component.js +330 -0
- package/dist/lib/builder/distribution-manager.component.js.map +1 -0
- package/dist/lib/builder/distribution.service.d.ts +62 -0
- package/dist/lib/builder/distribution.service.d.ts.map +1 -0
- package/dist/lib/builder/distribution.service.js +140 -0
- package/dist/lib/builder/distribution.service.js.map +1 -0
- package/dist/lib/builder/entity-names.d.ts +20 -0
- package/dist/lib/builder/entity-names.d.ts.map +1 -0
- package/dist/lib/builder/entity-names.js +20 -0
- package/dist/lib/builder/entity-names.js.map +1 -0
- package/dist/lib/builder/form-builder.component.d.ts +92 -0
- package/dist/lib/builder/form-builder.component.d.ts.map +1 -0
- package/dist/lib/builder/form-builder.component.js +627 -0
- package/dist/lib/builder/form-builder.component.js.map +1 -0
- package/dist/lib/builder/form-builder.styles.d.ts +3 -0
- package/dist/lib/builder/form-builder.styles.d.ts.map +1 -0
- package/dist/lib/builder/form-builder.styles.js +94 -0
- package/dist/lib/builder/form-builder.styles.js.map +1 -0
- package/dist/lib/builder/form-preview-modal.component.d.ts +25 -0
- package/dist/lib/builder/form-preview-modal.component.d.ts.map +1 -0
- package/dist/lib/builder/form-preview-modal.component.js +90 -0
- package/dist/lib/builder/form-preview-modal.component.js.map +1 -0
- package/dist/lib/builder/index.d.ts +31 -0
- package/dist/lib/builder/index.d.ts.map +1 -0
- package/dist/lib/builder/index.js +32 -0
- package/dist/lib/builder/index.js.map +1 -0
- package/dist/lib/builder/json-fields.d.ts +14 -0
- package/dist/lib/builder/json-fields.d.ts.map +1 -0
- package/dist/lib/builder/json-fields.js +100 -0
- package/dist/lib/builder/json-fields.js.map +1 -0
- package/dist/lib/builder/publish.service.d.ts +34 -0
- package/dist/lib/builder/publish.service.d.ts.map +1 -0
- package/dist/lib/builder/publish.service.js +110 -0
- package/dist/lib/builder/publish.service.js.map +1 -0
- package/dist/lib/builder/qr-code.d.ts +26 -0
- package/dist/lib/builder/qr-code.d.ts.map +1 -0
- package/dist/lib/builder/qr-code.js +361 -0
- package/dist/lib/builder/qr-code.js.map +1 -0
- package/dist/lib/builder/question-editor.component.d.ts +41 -0
- package/dist/lib/builder/question-editor.component.d.ts.map +1 -0
- package/dist/lib/builder/question-editor.component.js +228 -0
- package/dist/lib/builder/question-editor.component.js.map +1 -0
- package/dist/lib/builder/question-type-catalog.d.ts +29 -0
- package/dist/lib/builder/question-type-catalog.d.ts.map +1 -0
- package/dist/lib/builder/question-type-catalog.js +43 -0
- package/dist/lib/builder/question-type-catalog.js.map +1 -0
- package/dist/lib/builder/reorder.d.ts +10 -0
- package/dist/lib/builder/reorder.d.ts.map +1 -0
- package/dist/lib/builder/reorder.js +18 -0
- package/dist/lib/builder/reorder.js.map +1 -0
- package/dist/lib/builder/snapshot-builder.d.ts +16 -0
- package/dist/lib/builder/snapshot-builder.d.ts.map +1 -0
- package/dist/lib/builder/snapshot-builder.js +93 -0
- package/dist/lib/builder/snapshot-builder.js.map +1 -0
- package/dist/lib/builder/style-tokens.d.ts +54 -0
- package/dist/lib/builder/style-tokens.d.ts.map +1 -0
- package/dist/lib/builder/style-tokens.js +71 -0
- package/dist/lib/builder/style-tokens.js.map +1 -0
- package/dist/lib/builder/validation-rule-editor.component.d.ts +27 -0
- package/dist/lib/builder/validation-rule-editor.component.d.ts.map +1 -0
- package/dist/lib/builder/validation-rule-editor.component.js +179 -0
- package/dist/lib/builder/validation-rule-editor.component.js.map +1 -0
- package/dist/lib/dashboard/components/distribution-chart.component.d.ts +14 -0
- package/dist/lib/dashboard/components/distribution-chart.component.d.ts.map +1 -0
- package/dist/lib/dashboard/components/distribution-chart.component.js +85 -0
- package/dist/lib/dashboard/components/distribution-chart.component.js.map +1 -0
- package/dist/lib/dashboard/components/funnel-chart.component.d.ts +14 -0
- package/dist/lib/dashboard/components/funnel-chart.component.d.ts.map +1 -0
- package/dist/lib/dashboard/components/funnel-chart.component.js +101 -0
- package/dist/lib/dashboard/components/funnel-chart.component.js.map +1 -0
- package/dist/lib/dashboard/components/question-breakdown.component.d.ts +16 -0
- package/dist/lib/dashboard/components/question-breakdown.component.d.ts.map +1 -0
- package/dist/lib/dashboard/components/question-breakdown.component.js +213 -0
- package/dist/lib/dashboard/components/question-breakdown.component.js.map +1 -0
- package/dist/lib/dashboard/components/response-detail.component.d.ts +11 -0
- package/dist/lib/dashboard/components/response-detail.component.d.ts.map +1 -0
- package/dist/lib/dashboard/components/response-detail.component.js +113 -0
- package/dist/lib/dashboard/components/response-detail.component.js.map +1 -0
- package/dist/lib/dashboard/components/response-list.component.d.ts +27 -0
- package/dist/lib/dashboard/components/response-list.component.d.ts.map +1 -0
- package/dist/lib/dashboard/components/response-list.component.js +196 -0
- package/dist/lib/dashboard/components/response-list.component.js.map +1 -0
- package/dist/lib/dashboard/components/summary-stats.component.d.ts +12 -0
- package/dist/lib/dashboard/components/summary-stats.component.d.ts.map +1 -0
- package/dist/lib/dashboard/components/summary-stats.component.js +112 -0
- package/dist/lib/dashboard/components/summary-stats.component.js.map +1 -0
- package/dist/lib/dashboard/forms-reporting-dashboard.component.d.ts +64 -0
- package/dist/lib/dashboard/forms-reporting-dashboard.component.d.ts.map +1 -0
- package/dist/lib/dashboard/forms-reporting-dashboard.component.js +397 -0
- package/dist/lib/dashboard/forms-reporting-dashboard.component.js.map +1 -0
- package/dist/lib/dashboard/index.d.ts +19 -0
- package/dist/lib/dashboard/index.d.ts.map +1 -0
- package/dist/lib/dashboard/index.js +19 -0
- package/dist/lib/dashboard/index.js.map +1 -0
- package/dist/lib/dashboard/models/reporting.model.d.ts +125 -0
- package/dist/lib/dashboard/models/reporting.model.d.ts.map +1 -0
- package/dist/lib/dashboard/models/reporting.model.js +2 -0
- package/dist/lib/dashboard/models/reporting.model.js.map +1 -0
- package/dist/lib/dashboard/services/forms-reporting-export.service.d.ts +21 -0
- package/dist/lib/dashboard/services/forms-reporting-export.service.d.ts.map +1 -0
- package/dist/lib/dashboard/services/forms-reporting-export.service.js +83 -0
- package/dist/lib/dashboard/services/forms-reporting-export.service.js.map +1 -0
- package/dist/lib/dashboard/services/forms-reporting-mock.d.ts +18 -0
- package/dist/lib/dashboard/services/forms-reporting-mock.d.ts.map +1 -0
- package/dist/lib/dashboard/services/forms-reporting-mock.js +147 -0
- package/dist/lib/dashboard/services/forms-reporting-mock.js.map +1 -0
- package/dist/lib/dashboard/services/forms-reporting.service.d.ts +45 -0
- package/dist/lib/dashboard/services/forms-reporting.service.d.ts.map +1 -0
- package/dist/lib/dashboard/services/forms-reporting.service.js +230 -0
- package/dist/lib/dashboard/services/forms-reporting.service.js.map +1 -0
- package/dist/lib/dashboard/services/reporting-aggregations.d.ts +40 -0
- package/dist/lib/dashboard/services/reporting-aggregations.d.ts.map +1 -0
- package/dist/lib/dashboard/services/reporting-aggregations.js +379 -0
- package/dist/lib/dashboard/services/reporting-aggregations.js.map +1 -0
- package/dist/lib/generated/Entities/mjBizAppsCommonAddress/mjbizappscommonaddress.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/mjBizAppsCommonAddress/mjbizappscommonaddress.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/mjBizAppsCommonAddress/mjbizappscommonaddress.form.component.js +104 -0
- package/dist/lib/generated/Entities/mjBizAppsCommonAddress/mjbizappscommonaddress.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/mjBizAppsCommonAddressLink/mjbizappscommonaddresslink.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/mjBizAppsCommonAddressLink/mjbizappscommonaddresslink.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/mjBizAppsCommonAddressLink/mjbizappscommonaddresslink.form.component.js +83 -0
- package/dist/lib/generated/Entities/mjBizAppsCommonAddressLink/mjbizappscommonaddresslink.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/mjBizAppsCommonAddressType/mjbizappscommonaddresstype.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/mjBizAppsCommonAddressType/mjbizappscommonaddresstype.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/mjBizAppsCommonAddressType/mjbizappscommonaddresstype.form.component.js +96 -0
- package/dist/lib/generated/Entities/mjBizAppsCommonAddressType/mjbizappscommonaddresstype.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/mjBizAppsCommonContactMethod/mjbizappscommoncontactmethod.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/mjBizAppsCommonContactMethod/mjbizappscommoncontactmethod.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/mjBizAppsCommonContactMethod/mjbizappscommoncontactmethod.form.component.js +83 -0
- package/dist/lib/generated/Entities/mjBizAppsCommonContactMethod/mjbizappscommoncontactmethod.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/mjBizAppsCommonContactType/mjbizappscommoncontacttype.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/mjBizAppsCommonContactType/mjbizappscommoncontacttype.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/mjBizAppsCommonContactType/mjbizappscommoncontacttype.form.component.js +96 -0
- package/dist/lib/generated/Entities/mjBizAppsCommonContactType/mjbizappscommoncontacttype.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/mjBizAppsCommonOrganization/mjbizappscommonorganization.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/mjBizAppsCommonOrganization/mjbizappscommonorganization.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/mjBizAppsCommonOrganization/mjbizappscommonorganization.form.component.js +172 -0
- package/dist/lib/generated/Entities/mjBizAppsCommonOrganization/mjbizappscommonorganization.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/mjBizAppsCommonOrganizationType/mjbizappscommonorganizationtype.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/mjBizAppsCommonOrganizationType/mjbizappscommonorganizationtype.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/mjBizAppsCommonOrganizationType/mjbizappscommonorganizationtype.form.component.js +90 -0
- package/dist/lib/generated/Entities/mjBizAppsCommonOrganizationType/mjbizappscommonorganizationtype.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/mjBizAppsCommonPerson/mjbizappscommonperson.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/mjBizAppsCommonPerson/mjbizappscommonperson.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/mjBizAppsCommonPerson/mjbizappscommonperson.form.component.js +274 -0
- package/dist/lib/generated/Entities/mjBizAppsCommonPerson/mjbizappscommonperson.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/mjBizAppsCommonRelationship/mjbizappscommonrelationship.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/mjBizAppsCommonRelationship/mjbizappscommonrelationship.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/mjBizAppsCommonRelationship/mjbizappscommonrelationship.form.component.js +91 -0
- package/dist/lib/generated/Entities/mjBizAppsCommonRelationship/mjbizappscommonrelationship.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/mjBizAppsCommonRelationshipType/mjbizappscommonrelationshiptype.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/mjBizAppsCommonRelationshipType/mjbizappscommonrelationshiptype.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/mjBizAppsCommonRelationshipType/mjbizappscommonrelationshiptype.form.component.js +100 -0
- package/dist/lib/generated/Entities/mjBizAppsCommonRelationshipType/mjbizappscommonrelationshiptype.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/mjBizAppsFormsForm/mjbizappsformsform.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/mjBizAppsFormsForm/mjbizappsformsform.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/mjBizAppsFormsForm/mjbizappsformsform.form.component.js +174 -0
- package/dist/lib/generated/Entities/mjBizAppsFormsForm/mjbizappsformsform.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/mjBizAppsFormsFormCategory/mjbizappsformsformcategory.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/mjBizAppsFormsFormCategory/mjbizappsformsformcategory.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/mjBizAppsFormsFormCategory/mjbizappsformsformcategory.form.component.js +118 -0
- package/dist/lib/generated/Entities/mjBizAppsFormsFormCategory/mjbizappsformsformcategory.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/mjBizAppsFormsFormDistribution/mjbizappsformsformdistribution.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/mjBizAppsFormsFormDistribution/mjbizappsformsformdistribution.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/mjBizAppsFormsFormDistribution/mjbizappsformsformdistribution.form.component.js +93 -0
- package/dist/lib/generated/Entities/mjBizAppsFormsFormDistribution/mjbizappsformsformdistribution.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/mjBizAppsFormsFormPage/mjbizappsformsformpage.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/mjBizAppsFormsFormPage/mjbizappsformsformpage.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/mjBizAppsFormsFormPage/mjbizappsformsformpage.form.component.js +96 -0
- package/dist/lib/generated/Entities/mjBizAppsFormsFormPage/mjbizappsformsformpage.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/mjBizAppsFormsFormQuestion/mjbizappsformsformquestion.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/mjBizAppsFormsFormQuestion/mjbizappsformsformquestion.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/mjBizAppsFormsFormQuestion/mjbizappsformsformquestion.form.component.js +132 -0
- package/dist/lib/generated/Entities/mjBizAppsFormsFormQuestion/mjbizappsformsformquestion.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/mjBizAppsFormsFormQuestionOption/mjbizappsformsformquestionoption.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/mjBizAppsFormsFormQuestionOption/mjbizappsformsformquestionoption.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/mjBizAppsFormsFormQuestionOption/mjbizappsformsformquestionoption.form.component.js +77 -0
- package/dist/lib/generated/Entities/mjBizAppsFormsFormQuestionOption/mjbizappsformsformquestionoption.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/mjBizAppsFormsFormResponse/mjbizappsformsformresponse.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/mjBizAppsFormsFormResponse/mjbizappsformsformresponse.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/mjBizAppsFormsFormResponse/mjbizappsformsformresponse.form.component.js +108 -0
- package/dist/lib/generated/Entities/mjBizAppsFormsFormResponse/mjbizappsformsformresponse.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/mjBizAppsFormsFormResponseAnswer/mjbizappsformsformresponseanswer.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/mjBizAppsFormsFormResponseAnswer/mjbizappsformsformresponseanswer.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/mjBizAppsFormsFormResponseAnswer/mjbizappsformsformresponseanswer.form.component.js +99 -0
- package/dist/lib/generated/Entities/mjBizAppsFormsFormResponseAnswer/mjbizappsformsformresponseanswer.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/mjBizAppsFormsFormStyle/mjbizappsformsformstyle.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/mjBizAppsFormsFormStyle/mjbizappsformsformstyle.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/mjBizAppsFormsFormStyle/mjbizappsformsformstyle.form.component.js +100 -0
- package/dist/lib/generated/Entities/mjBizAppsFormsFormStyle/mjbizappsformsformstyle.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/mjBizAppsFormsFormVersion/mjbizappsformsformversion.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/mjBizAppsFormsFormVersion/mjbizappsformsformversion.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/mjBizAppsFormsFormVersion/mjbizappsformsformversion.form.component.js +96 -0
- package/dist/lib/generated/Entities/mjBizAppsFormsFormVersion/mjbizappsformsformversion.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/mjBizAppsTasksTask/mjbizappstaskstask.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/mjBizAppsTasksTask/mjbizappstaskstask.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/mjBizAppsTasksTask/mjbizappstaskstask.form.component.js +274 -0
- package/dist/lib/generated/Entities/mjBizAppsTasksTask/mjbizappstaskstask.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/mjBizAppsTasksTaskActivity/mjbizappstaskstaskactivity.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/mjBizAppsTasksTaskActivity/mjbizappstaskstaskactivity.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/mjBizAppsTasksTaskActivity/mjbizappstaskstaskactivity.form.component.js +67 -0
- package/dist/lib/generated/Entities/mjBizAppsTasksTaskActivity/mjbizappstaskstaskactivity.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/mjBizAppsTasksTaskAssignment/mjbizappstaskstaskassignment.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/mjBizAppsTasksTaskAssignment/mjbizappstaskstaskassignment.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/mjBizAppsTasksTaskAssignment/mjbizappstaskstaskassignment.form.component.js +90 -0
- package/dist/lib/generated/Entities/mjBizAppsTasksTaskAssignment/mjbizappstaskstaskassignment.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/mjBizAppsTasksTaskCategory/mjbizappstaskstaskcategory.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/mjBizAppsTasksTaskCategory/mjbizappstaskstaskcategory.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/mjBizAppsTasksTaskCategory/mjbizappstaskstaskcategory.form.component.js +124 -0
- package/dist/lib/generated/Entities/mjBizAppsTasksTaskCategory/mjbizappstaskstaskcategory.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/mjBizAppsTasksTaskComment/mjbizappstaskstaskcomment.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/mjBizAppsTasksTaskComment/mjbizappstaskstaskcomment.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/mjBizAppsTasksTaskComment/mjbizappstaskstaskcomment.form.component.js +86 -0
- package/dist/lib/generated/Entities/mjBizAppsTasksTaskComment/mjbizappstaskstaskcomment.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/mjBizAppsTasksTaskDecision/mjbizappstaskstaskdecision.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/mjBizAppsTasksTaskDecision/mjbizappstaskstaskdecision.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/mjBizAppsTasksTaskDecision/mjbizappstaskstaskdecision.form.component.js +67 -0
- package/dist/lib/generated/Entities/mjBizAppsTasksTaskDecision/mjbizappstaskstaskdecision.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/mjBizAppsTasksTaskDecisionOutcome/mjbizappstaskstaskdecisionoutcome.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/mjBizAppsTasksTaskDecisionOutcome/mjbizappstaskstaskdecisionoutcome.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/mjBizAppsTasksTaskDecisionOutcome/mjbizappstaskstaskdecisionoutcome.form.component.js +86 -0
- package/dist/lib/generated/Entities/mjBizAppsTasksTaskDecisionOutcome/mjbizappstaskstaskdecisionoutcome.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/mjBizAppsTasksTaskDependency/mjbizappstaskstaskdependency.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/mjBizAppsTasksTaskDependency/mjbizappstaskstaskdependency.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/mjBizAppsTasksTaskDependency/mjbizappstaskstaskdependency.form.component.js +61 -0
- package/dist/lib/generated/Entities/mjBizAppsTasksTaskDependency/mjbizappstaskstaskdependency.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/mjBizAppsTasksTaskLink/mjbizappstaskstasklink.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/mjBizAppsTasksTaskLink/mjbizappstaskstasklink.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/mjBizAppsTasksTaskLink/mjbizappstaskstasklink.form.component.js +63 -0
- package/dist/lib/generated/Entities/mjBizAppsTasksTaskLink/mjbizappstaskstasklink.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/mjBizAppsTasksTaskNotificationConfig/mjbizappstaskstasknotificationconfig.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/mjBizAppsTasksTaskNotificationConfig/mjbizappstaskstasknotificationconfig.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/mjBizAppsTasksTaskNotificationConfig/mjbizappstaskstasknotificationconfig.form.component.js +69 -0
- package/dist/lib/generated/Entities/mjBizAppsTasksTaskNotificationConfig/mjbizappstaskstasknotificationconfig.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/mjBizAppsTasksTaskNotificationLog/mjbizappstaskstasknotificationlog.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/mjBizAppsTasksTaskNotificationLog/mjbizappstaskstasknotificationlog.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/mjBizAppsTasksTaskNotificationLog/mjbizappstaskstasknotificationlog.form.component.js +63 -0
- package/dist/lib/generated/Entities/mjBizAppsTasksTaskNotificationLog/mjbizappstaskstasknotificationlog.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/mjBizAppsTasksTaskRole/mjbizappstaskstaskrole.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/mjBizAppsTasksTaskRole/mjbizappstaskstaskrole.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/mjBizAppsTasksTaskRole/mjbizappstaskstaskrole.form.component.js +98 -0
- package/dist/lib/generated/Entities/mjBizAppsTasksTaskRole/mjbizappstaskstaskrole.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/mjBizAppsTasksTaskTag/mjbizappstaskstasktag.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/mjBizAppsTasksTaskTag/mjbizappstaskstasktag.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/mjBizAppsTasksTaskTag/mjbizappstaskstasktag.form.component.js +80 -0
- package/dist/lib/generated/Entities/mjBizAppsTasksTaskTag/mjbizappstaskstasktag.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/mjBizAppsTasksTaskTagLink/mjbizappstaskstasktaglink.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/mjBizAppsTasksTaskTagLink/mjbizappstaskstasktaglink.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/mjBizAppsTasksTaskTagLink/mjbizappstaskstasktaglink.form.component.js +59 -0
- package/dist/lib/generated/Entities/mjBizAppsTasksTaskTagLink/mjbizappstaskstasktaglink.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/mjBizAppsTasksTaskTemplate/mjbizappstaskstasktemplate.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/mjBizAppsTasksTaskTemplate/mjbizappstaskstasktemplate.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/mjBizAppsTasksTaskTemplate/mjbizappstaskstasktemplate.form.component.js +84 -0
- package/dist/lib/generated/Entities/mjBizAppsTasksTaskTemplate/mjbizappstaskstasktemplate.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/mjBizAppsTasksTaskTemplateItem/mjbizappstaskstasktemplateitem.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/mjBizAppsTasksTaskTemplateItem/mjbizappstaskstasktemplateitem.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/mjBizAppsTasksTaskTemplateItem/mjbizappstaskstasktemplateitem.form.component.js +146 -0
- package/dist/lib/generated/Entities/mjBizAppsTasksTaskTemplateItem/mjbizappstaskstasktemplateitem.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/mjBizAppsTasksTaskTemplateItemDependency/mjbizappstaskstasktemplateitemdependency.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/mjBizAppsTasksTaskTemplateItemDependency/mjbizappstaskstasktemplateitemdependency.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/mjBizAppsTasksTaskTemplateItemDependency/mjbizappstaskstasktemplateitemdependency.form.component.js +61 -0
- package/dist/lib/generated/Entities/mjBizAppsTasksTaskTemplateItemDependency/mjbizappstaskstasktemplateitemdependency.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/mjBizAppsTasksTaskTemplateItemRole/mjbizappstaskstasktemplateitemrole.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/mjBizAppsTasksTaskTemplateItemRole/mjbizappstaskstasktemplateitemrole.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/mjBizAppsTasksTaskTemplateItemRole/mjbizappstaskstasktemplateitemrole.form.component.js +59 -0
- package/dist/lib/generated/Entities/mjBizAppsTasksTaskTemplateItemRole/mjbizappstaskstasktemplateitemrole.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/mjBizAppsTasksTaskType/mjbizappstaskstasktype.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/mjBizAppsTasksTaskType/mjbizappstaskstasktype.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/mjBizAppsTasksTaskType/mjbizappstaskstasktype.form.component.js +132 -0
- package/dist/lib/generated/Entities/mjBizAppsTasksTaskType/mjbizappstaskstasktype.form.component.js.map +1 -0
- package/dist/lib/generated/class-registrations-manifest.d.ts +6 -0
- package/dist/lib/generated/class-registrations-manifest.d.ts.map +1 -0
- package/dist/lib/generated/class-registrations-manifest.js +6 -0
- package/dist/lib/generated/class-registrations-manifest.js.map +1 -0
- package/dist/lib/generated/generated-forms.module.d.ts +61 -0
- package/dist/lib/generated/generated-forms.module.d.ts.map +1 -0
- package/dist/lib/generated/generated-forms.module.js +207 -0
- package/dist/lib/generated/generated-forms.module.js.map +1 -0
- package/dist/lib/home/forms-home-dashboard.component.d.ts +61 -0
- package/dist/lib/home/forms-home-dashboard.component.d.ts.map +1 -0
- package/dist/lib/home/forms-home-dashboard.component.js +379 -0
- package/dist/lib/home/forms-home-dashboard.component.js.map +1 -0
- package/dist/lib/home/forms-home.service.d.ts +24 -0
- package/dist/lib/home/forms-home.service.d.ts.map +1 -0
- package/dist/lib/home/forms-home.service.js +92 -0
- package/dist/lib/home/forms-home.service.js.map +1 -0
- package/dist/lib/home/home-aggregations.d.ts +23 -0
- package/dist/lib/home/home-aggregations.d.ts.map +1 -0
- package/dist/lib/home/home-aggregations.js +64 -0
- package/dist/lib/home/home-aggregations.js.map +1 -0
- package/dist/lib/home/home-models.d.ts +60 -0
- package/dist/lib/home/home-models.d.ts.map +1 -0
- package/dist/lib/home/home-models.js +34 -0
- package/dist/lib/home/home-models.js.map +1 -0
- package/dist/lib/home/index.d.ts +13 -0
- package/dist/lib/home/index.d.ts.map +1 -0
- package/dist/lib/home/index.js +13 -0
- package/dist/lib/home/index.js.map +1 -0
- package/dist/lib/widget/api/form-upload.service.d.ts +41 -0
- package/dist/lib/widget/api/form-upload.service.d.ts.map +1 -0
- package/dist/lib/widget/api/form-upload.service.js +124 -0
- package/dist/lib/widget/api/form-upload.service.js.map +1 -0
- package/dist/lib/widget/api/forms-api.config.d.ts +55 -0
- package/dist/lib/widget/api/forms-api.config.d.ts.map +1 -0
- package/dist/lib/widget/api/forms-api.config.js +40 -0
- package/dist/lib/widget/api/forms-api.config.js.map +1 -0
- package/dist/lib/widget/api/forms-api.graphql.service.d.ts +20 -0
- package/dist/lib/widget/api/forms-api.graphql.service.d.ts.map +1 -0
- package/dist/lib/widget/api/forms-api.graphql.service.js +96 -0
- package/dist/lib/widget/api/forms-api.graphql.service.js.map +1 -0
- package/dist/lib/widget/api/forms-api.interface.d.ts +45 -0
- package/dist/lib/widget/api/forms-api.interface.d.ts.map +1 -0
- package/dist/lib/widget/api/forms-api.interface.js +8 -0
- package/dist/lib/widget/api/forms-api.interface.js.map +1 -0
- package/dist/lib/widget/api/forms-api.mock.service.d.ts +12 -0
- package/dist/lib/widget/api/forms-api.mock.service.d.ts.map +1 -0
- package/dist/lib/widget/api/forms-api.mock.service.js +41 -0
- package/dist/lib/widget/api/forms-api.mock.service.js.map +1 -0
- package/dist/lib/widget/api/mock-form.data.d.ts +8 -0
- package/dist/lib/widget/api/mock-form.data.d.ts.map +1 -0
- package/dist/lib/widget/api/mock-form.data.js +192 -0
- package/dist/lib/widget/api/mock-form.data.js.map +1 -0
- package/dist/lib/widget/api/submission-mapping.d.ts +60 -0
- package/dist/lib/widget/api/submission-mapping.d.ts.map +1 -0
- package/dist/lib/widget/api/submission-mapping.js +47 -0
- package/dist/lib/widget/api/submission-mapping.js.map +1 -0
- package/dist/lib/widget/components/form-one-question.component.d.ts +43 -0
- package/dist/lib/widget/components/form-one-question.component.d.ts.map +1 -0
- package/dist/lib/widget/components/form-one-question.component.js +194 -0
- package/dist/lib/widget/components/form-one-question.component.js.map +1 -0
- package/dist/lib/widget/components/form-progress.component.d.ts +9 -0
- package/dist/lib/widget/components/form-progress.component.d.ts.map +1 -0
- package/dist/lib/widget/components/form-progress.component.js +47 -0
- package/dist/lib/widget/components/form-progress.component.js.map +1 -0
- package/dist/lib/widget/components/form-scroll.component.d.ts +23 -0
- package/dist/lib/widget/components/form-scroll.component.d.ts.map +1 -0
- package/dist/lib/widget/components/form-scroll.component.js +132 -0
- package/dist/lib/widget/components/form-scroll.component.js.map +1 -0
- package/dist/lib/widget/components/questions/form-question.component.d.ts +68 -0
- package/dist/lib/widget/components/questions/form-question.component.d.ts.map +1 -0
- package/dist/lib/widget/components/questions/form-question.component.js +541 -0
- package/dist/lib/widget/components/questions/form-question.component.js.map +1 -0
- package/dist/lib/widget/components/questions/input-mode.d.ts +13 -0
- package/dist/lib/widget/components/questions/input-mode.d.ts.map +1 -0
- package/dist/lib/widget/components/questions/input-mode.js +42 -0
- package/dist/lib/widget/components/questions/input-mode.js.map +1 -0
- package/dist/lib/widget/components/turnstile-challenge.component.d.ts +52 -0
- package/dist/lib/widget/components/turnstile-challenge.component.d.ts.map +1 -0
- package/dist/lib/widget/components/turnstile-challenge.component.js +123 -0
- package/dist/lib/widget/components/turnstile-challenge.component.js.map +1 -0
- package/dist/lib/widget/core/answer-value.d.ts +17 -0
- package/dist/lib/widget/core/answer-value.d.ts.map +1 -0
- package/dist/lib/widget/core/answer-value.js +41 -0
- package/dist/lib/widget/core/answer-value.js.map +1 -0
- package/dist/lib/widget/core/autosave-controller.d.ts +65 -0
- package/dist/lib/widget/core/autosave-controller.d.ts.map +1 -0
- package/dist/lib/widget/core/autosave-controller.js +134 -0
- package/dist/lib/widget/core/autosave-controller.js.map +1 -0
- package/dist/lib/widget/core/client-id.d.ts +17 -0
- package/dist/lib/widget/core/client-id.d.ts.map +1 -0
- package/dist/lib/widget/core/client-id.js +52 -0
- package/dist/lib/widget/core/client-id.js.map +1 -0
- package/dist/lib/widget/core/form-runtime.d.ts +34 -0
- package/dist/lib/widget/core/form-runtime.d.ts.map +1 -0
- package/dist/lib/widget/core/form-runtime.js +123 -0
- package/dist/lib/widget/core/form-runtime.js.map +1 -0
- package/dist/lib/widget/core/one-question-stepper.d.ts +20 -0
- package/dist/lib/widget/core/one-question-stepper.d.ts.map +1 -0
- package/dist/lib/widget/core/one-question-stepper.js +23 -0
- package/dist/lib/widget/core/one-question-stepper.js.map +1 -0
- package/dist/lib/widget/core/submit-phase.d.ts +31 -0
- package/dist/lib/widget/core/submit-phase.d.ts.map +1 -0
- package/dist/lib/widget/core/submit-phase.js +21 -0
- package/dist/lib/widget/core/submit-phase.js.map +1 -0
- package/dist/lib/widget/core/theming.d.ts +17 -0
- package/dist/lib/widget/core/theming.d.ts.map +1 -0
- package/dist/lib/widget/core/theming.js +36 -0
- package/dist/lib/widget/core/theming.js.map +1 -0
- package/dist/lib/widget/core/turnstile-gate.d.ts +42 -0
- package/dist/lib/widget/core/turnstile-gate.d.ts.map +1 -0
- package/dist/lib/widget/core/turnstile-gate.js +61 -0
- package/dist/lib/widget/core/turnstile-gate.js.map +1 -0
- package/dist/lib/widget/core/turnstile-loader.d.ts +34 -0
- package/dist/lib/widget/core/turnstile-loader.d.ts.map +1 -0
- package/dist/lib/widget/core/turnstile-loader.js +68 -0
- package/dist/lib/widget/core/turnstile-loader.js.map +1 -0
- package/dist/lib/widget/core/validation.d.ts +19 -0
- package/dist/lib/widget/core/validation.d.ts.map +1 -0
- package/dist/lib/widget/core/validation.js +105 -0
- package/dist/lib/widget/core/validation.js.map +1 -0
- package/dist/lib/widget/index.d.ts +27 -0
- package/dist/lib/widget/index.d.ts.map +1 -0
- package/dist/lib/widget/index.js +30 -0
- package/dist/lib/widget/index.js.map +1 -0
- package/dist/lib/widget/mj-form.component.d.ts +114 -0
- package/dist/lib/widget/mj-form.component.d.ts.map +1 -0
- package/dist/lib/widget/mj-form.component.js +428 -0
- package/dist/lib/widget/mj-form.component.js.map +1 -0
- package/dist/lib/widget/register-element.d.ts +8 -0
- package/dist/lib/widget/register-element.d.ts.map +1 -0
- package/dist/lib/widget/register-element.js +98 -0
- package/dist/lib/widget/register-element.js.map +1 -0
- package/dist/public-api.d.ts +23 -0
- package/dist/public-api.d.ts.map +1 -0
- package/dist/public-api.js +33 -0
- package/dist/public-api.js.map +1 -0
- package/dist/widget-entry.d.ts +2 -0
- package/dist/widget-entry.d.ts.map +1 -0
- package/dist/widget-entry.js +20 -0
- package/dist/widget-entry.js.map +1 -0
- package/package.json +53 -5
- package/README.md +0 -3
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Forms reporting data service (WP-F).
|
|
3
|
+
*
|
|
4
|
+
* Pure RunView/RunViews + snapshot-parsing — NO new infra (FORMS_BUILD_PLAN §8.1).
|
|
5
|
+
* Loads the reportable forms, then for a selected form version: the published
|
|
6
|
+
* snapshot (for question labels/options), the responses, and the answers, and
|
|
7
|
+
* folds them into the `FormReportData` read-model. Stateless and injectable; the
|
|
8
|
+
* dashboard owns selection state.
|
|
9
|
+
*/
|
|
10
|
+
import { Injectable } from '@angular/core';
|
|
11
|
+
import { RunView } from '@memberjunction/core';
|
|
12
|
+
import { flattenQuestions, buildSummary, buildBreakdowns, buildFunnel, buildResponseRows, buildResponseDetail, } from './reporting-aggregations';
|
|
13
|
+
import * as i0 from "@angular/core";
|
|
14
|
+
/** Entity names (PHASE1_DECOMPOSITION entity-name table). */
|
|
15
|
+
const ENTITY = {
|
|
16
|
+
forms: 'MJ_BizApps_Forms: Forms',
|
|
17
|
+
versions: 'MJ_BizApps_Forms: Form Versions',
|
|
18
|
+
responses: 'MJ_BizApps_Forms: Form Responses',
|
|
19
|
+
answers: 'MJ_BizApps_Forms: Form Response Answers',
|
|
20
|
+
};
|
|
21
|
+
/** DB schema for the Forms tables/views — the IN-subquery view must be qualified. */
|
|
22
|
+
const FORMS_SCHEMA = '__mj_BizAppsForms';
|
|
23
|
+
/**
|
|
24
|
+
* Build the answers `ExtraFilter` that scopes to a form's responses across all versions.
|
|
25
|
+
* The `vwFormResponses` view MUST be schema-qualified: the connection's default schema is
|
|
26
|
+
* not `__mj_BizAppsForms`, so a bare name resolves against `dbo` and throws
|
|
27
|
+
* "Invalid object name 'vwFormResponses'". Exported for unit testing.
|
|
28
|
+
*/
|
|
29
|
+
export function answersForFormFilter(formId) {
|
|
30
|
+
return `ResponseID IN (SELECT ID FROM ${FORMS_SCHEMA}.vwFormResponses WHERE FormID='${formId}')`;
|
|
31
|
+
}
|
|
32
|
+
export class FormsReportingService {
|
|
33
|
+
rv = new RunView();
|
|
34
|
+
/**
|
|
35
|
+
* Lists forms that have at least one published version, with their latest
|
|
36
|
+
* published version id and COMPLETE response count, for the form picker. Partial
|
|
37
|
+
* (in-progress) autosaves are excluded from the count.
|
|
38
|
+
*/
|
|
39
|
+
async loadReportableForms() {
|
|
40
|
+
const [formsRes, versionsRes, responsesRes] = await this.rv.RunViews([
|
|
41
|
+
{
|
|
42
|
+
EntityName: ENTITY.forms,
|
|
43
|
+
ResultType: 'simple',
|
|
44
|
+
Fields: ['ID', 'Name'],
|
|
45
|
+
OrderBy: 'Name',
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
EntityName: ENTITY.versions,
|
|
49
|
+
ExtraFilter: `Status='Published'`,
|
|
50
|
+
ResultType: 'simple',
|
|
51
|
+
Fields: ['ID', 'FormID', 'VersionNumber'],
|
|
52
|
+
OrderBy: 'VersionNumber DESC',
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
EntityName: ENTITY.responses,
|
|
56
|
+
// Headline response count is COMPLETE-only: in-progress Partial autosaves are not
|
|
57
|
+
// "responses". (Partials still feed the drop-off funnel in loadReport, which reads
|
|
58
|
+
// its own rows.)
|
|
59
|
+
ExtraFilter: `Status='Complete'`,
|
|
60
|
+
ResultType: 'simple',
|
|
61
|
+
Fields: ['ID', 'FormID', 'Status'],
|
|
62
|
+
},
|
|
63
|
+
]);
|
|
64
|
+
if (!formsRes.Success || !versionsRes.Success || !responsesRes.Success) {
|
|
65
|
+
throw new Error(formsRes.ErrorMessage ||
|
|
66
|
+
versionsRes.ErrorMessage ||
|
|
67
|
+
responsesRes.ErrorMessage ||
|
|
68
|
+
'Failed to load reportable forms.');
|
|
69
|
+
}
|
|
70
|
+
const latestVersionByForm = new Map();
|
|
71
|
+
for (const v of versionsRes.Results) {
|
|
72
|
+
// Versions are ordered DESC, so the first seen per form is the latest.
|
|
73
|
+
if (!latestVersionByForm.has(v.FormID)) {
|
|
74
|
+
latestVersionByForm.set(v.FormID, v.ID);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
const responseCountByForm = new Map();
|
|
78
|
+
for (const r of responsesRes.Results) {
|
|
79
|
+
responseCountByForm.set(r.FormID, (responseCountByForm.get(r.FormID) ?? 0) + 1);
|
|
80
|
+
}
|
|
81
|
+
const out = [];
|
|
82
|
+
for (const f of formsRes.Results) {
|
|
83
|
+
const formVersionId = latestVersionByForm.get(f.ID);
|
|
84
|
+
if (!formVersionId) {
|
|
85
|
+
continue; // skip forms with no published version
|
|
86
|
+
}
|
|
87
|
+
out.push({
|
|
88
|
+
formId: f.ID,
|
|
89
|
+
formVersionId,
|
|
90
|
+
name: f.Name,
|
|
91
|
+
responseCount: responseCountByForm.get(f.ID) ?? 0,
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
return out;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Loads the full report bundle for a form — across ALL its versions.
|
|
98
|
+
*
|
|
99
|
+
* Responses are scoped by `FormID`, NOT by a single `FormVersionID`. Every response
|
|
100
|
+
* pins the form version that was live at submission, so a form with multiple
|
|
101
|
+
* published versions has responses spread across them; filtering to only the latest
|
|
102
|
+
* version silently hides every response submitted against an earlier one (the "I
|
|
103
|
+
* submitted a response but the dashboard shows nothing" bug). Question labels/options
|
|
104
|
+
* come from the latest published definition; answers map back by `QuestionID`.
|
|
105
|
+
*/
|
|
106
|
+
async loadReport(form) {
|
|
107
|
+
const definition = await this.loadDefinition(form.formVersionId);
|
|
108
|
+
const questions = flattenQuestions(definition);
|
|
109
|
+
const [responsesRes, answersRes] = await this.rv.RunViews([
|
|
110
|
+
{
|
|
111
|
+
EntityName: ENTITY.responses,
|
|
112
|
+
ExtraFilter: `FormID='${form.formId}'`,
|
|
113
|
+
ResultType: 'simple',
|
|
114
|
+
Fields: [
|
|
115
|
+
'ID',
|
|
116
|
+
'Status',
|
|
117
|
+
'StartedAt',
|
|
118
|
+
'SubmittedAt',
|
|
119
|
+
'RespondentPerson',
|
|
120
|
+
'AnonymousSessionID',
|
|
121
|
+
],
|
|
122
|
+
OrderBy: 'SubmittedAt DESC',
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
EntityName: ENTITY.answers,
|
|
126
|
+
ExtraFilter: answersForFormFilter(form.formId),
|
|
127
|
+
ResultType: 'simple',
|
|
128
|
+
Fields: [
|
|
129
|
+
'ID',
|
|
130
|
+
'ResponseID',
|
|
131
|
+
'QuestionID',
|
|
132
|
+
'TextValue',
|
|
133
|
+
'NumericValue',
|
|
134
|
+
'DateValue',
|
|
135
|
+
'BooleanValue',
|
|
136
|
+
'JSONValue',
|
|
137
|
+
'FileID',
|
|
138
|
+
],
|
|
139
|
+
},
|
|
140
|
+
]);
|
|
141
|
+
if (!responsesRes.Success || !answersRes.Success) {
|
|
142
|
+
throw new Error(responsesRes.ErrorMessage ||
|
|
143
|
+
answersRes.ErrorMessage ||
|
|
144
|
+
'Failed to load responses.');
|
|
145
|
+
}
|
|
146
|
+
const responses = responsesRes.Results;
|
|
147
|
+
const answers = answersRes.Results;
|
|
148
|
+
return {
|
|
149
|
+
form,
|
|
150
|
+
questions,
|
|
151
|
+
summary: buildSummary(responses),
|
|
152
|
+
breakdowns: buildBreakdowns(questions, answers),
|
|
153
|
+
funnel: buildFunnel(definition, answers),
|
|
154
|
+
responses: buildResponseRows(responses, answers),
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Loads one response's labelled answers for the detail view.
|
|
159
|
+
*/
|
|
160
|
+
async loadResponseDetail(responseId, questions) {
|
|
161
|
+
const [responseRes, answersRes] = await this.rv.RunViews([
|
|
162
|
+
{
|
|
163
|
+
EntityName: ENTITY.responses,
|
|
164
|
+
ExtraFilter: `ID='${responseId}'`,
|
|
165
|
+
ResultType: 'simple',
|
|
166
|
+
Fields: ['ID', 'Status', 'StartedAt', 'SubmittedAt', 'RespondentPerson', 'AnonymousSessionID'],
|
|
167
|
+
},
|
|
168
|
+
{
|
|
169
|
+
EntityName: ENTITY.answers,
|
|
170
|
+
ExtraFilter: `ResponseID='${responseId}'`,
|
|
171
|
+
ResultType: 'simple',
|
|
172
|
+
Fields: ['ID', 'ResponseID', 'QuestionID', 'TextValue', 'NumericValue', 'DateValue', 'BooleanValue', 'JSONValue', 'FileID'],
|
|
173
|
+
},
|
|
174
|
+
]);
|
|
175
|
+
if (!responseRes.Success || !answersRes.Success || responseRes.Results.length === 0) {
|
|
176
|
+
throw new Error(responseRes.ErrorMessage || answersRes.ErrorMessage || 'Response not found.');
|
|
177
|
+
}
|
|
178
|
+
return buildResponseDetail(responseRes.Results[0], answersRes.Results, questions);
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Loads all answer rows for a form (across ALL its versions' responses). Used by the
|
|
182
|
+
* export service to pivot responses into a wide matrix. Scoped by `FormID` for the
|
|
183
|
+
* same reason as {@link loadReport} — responses span versions.
|
|
184
|
+
*/
|
|
185
|
+
async loadAnswersForForm(formId) {
|
|
186
|
+
const res = (await this.rv.RunView({
|
|
187
|
+
EntityName: ENTITY.answers,
|
|
188
|
+
ExtraFilter: answersForFormFilter(formId),
|
|
189
|
+
ResultType: 'simple',
|
|
190
|
+
Fields: [
|
|
191
|
+
'ID',
|
|
192
|
+
'ResponseID',
|
|
193
|
+
'QuestionID',
|
|
194
|
+
'TextValue',
|
|
195
|
+
'NumericValue',
|
|
196
|
+
'DateValue',
|
|
197
|
+
'BooleanValue',
|
|
198
|
+
'JSONValue',
|
|
199
|
+
'FileID',
|
|
200
|
+
],
|
|
201
|
+
}));
|
|
202
|
+
if (!res.Success) {
|
|
203
|
+
throw new Error(res.ErrorMessage || 'Failed to load answers.');
|
|
204
|
+
}
|
|
205
|
+
return res.Results;
|
|
206
|
+
}
|
|
207
|
+
/** Loads + parses the published `DefinitionSnapshot` for a version. */
|
|
208
|
+
async loadDefinition(formVersionId) {
|
|
209
|
+
const res = (await this.rv.RunView({
|
|
210
|
+
EntityName: ENTITY.versions,
|
|
211
|
+
ExtraFilter: `ID='${formVersionId}'`,
|
|
212
|
+
ResultType: 'simple',
|
|
213
|
+
Fields: ['ID', 'DefinitionSnapshot'],
|
|
214
|
+
}));
|
|
215
|
+
if (!res.Success || res.Results.length === 0) {
|
|
216
|
+
throw new Error(res.ErrorMessage || 'Form version not found.');
|
|
217
|
+
}
|
|
218
|
+
const snapshot = res.Results[0].DefinitionSnapshot;
|
|
219
|
+
if (!snapshot) {
|
|
220
|
+
throw new Error('This form version has no published definition snapshot.');
|
|
221
|
+
}
|
|
222
|
+
return JSON.parse(snapshot);
|
|
223
|
+
}
|
|
224
|
+
static ɵfac = function FormsReportingService_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || FormsReportingService)(); };
|
|
225
|
+
static ɵprov = /*@__PURE__*/ i0.ɵɵdefineInjectable({ token: FormsReportingService, factory: FormsReportingService.ɵfac });
|
|
226
|
+
}
|
|
227
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(FormsReportingService, [{
|
|
228
|
+
type: Injectable
|
|
229
|
+
}], null, null); })();
|
|
230
|
+
//# sourceMappingURL=forms-reporting.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"forms-reporting.service.js","sourceRoot":"","sources":["../../../../src/lib/dashboard/services/forms-reporting.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure aggregation helpers for the Forms reporting dashboard (WP-F).
|
|
3
|
+
*
|
|
4
|
+
* Deliberately free of Angular / RunView so they are trivially unit-testable:
|
|
5
|
+
* each takes already-fetched rows + the published snapshot and returns a piece
|
|
6
|
+
* of the `FormReportData` read-model. The service layer does the I/O.
|
|
7
|
+
*/
|
|
8
|
+
import type { mjBizAppsFormsFormResponseEntityType, mjBizAppsFormsFormResponseAnswerEntityType, PublishedFormDefinition, PublishedFormQuestion, FormQuestionType } from '@mj-biz-apps/forms-entities';
|
|
9
|
+
import type { FormSummaryStats, QuestionBreakdown, BreakdownKind, FunnelStep, ResponseListRow, ResponseDetail } from '../models/reporting.model';
|
|
10
|
+
type ResponseRow = mjBizAppsFormsFormResponseEntityType;
|
|
11
|
+
type AnswerRow = mjBizAppsFormsFormResponseAnswerEntityType;
|
|
12
|
+
/** Flattens a definition's pages into questions in page/display order. */
|
|
13
|
+
export declare function flattenQuestions(def: PublishedFormDefinition): PublishedFormQuestion[];
|
|
14
|
+
/** Maps a question type to the breakdown visualisation kind. */
|
|
15
|
+
export declare function breakdownKindFor(type: FormQuestionType): BreakdownKind;
|
|
16
|
+
/**
|
|
17
|
+
* Builds top-line summary stats from response rows.
|
|
18
|
+
*
|
|
19
|
+
* The HEADLINE `totalResponses` counts COMPLETE responses only — a Partial row is an
|
|
20
|
+
* in-progress autosave, not a submitted response, and must never inflate the count a form
|
|
21
|
+
* owner sees. `partialResponses` still surfaces the in-progress count separately, and
|
|
22
|
+
* `completionRate` is complete / (complete + partial) so the drop-off signal is preserved.
|
|
23
|
+
*/
|
|
24
|
+
export declare function buildSummary(responses: ResponseRow[]): FormSummaryStats;
|
|
25
|
+
/** Builds per-question breakdowns. */
|
|
26
|
+
export declare function buildBreakdowns(questions: PublishedFormQuestion[], answers: AnswerRow[]): QuestionBreakdown[];
|
|
27
|
+
/** Builds the page completion / drop-off funnel. */
|
|
28
|
+
export declare function buildFunnel(def: PublishedFormDefinition, answers: AnswerRow[]): FunnelStep[];
|
|
29
|
+
/**
|
|
30
|
+
* Builds the response-list rows. Lists COMPLETE responses only — a Partial is an in-progress
|
|
31
|
+
* autosave, not a submitted response, so it must not appear in the headline response list
|
|
32
|
+
* (it is still reflected in the funnel/drop-off metric, which reads all answers).
|
|
33
|
+
*/
|
|
34
|
+
export declare function buildResponseRows(responses: ResponseRow[], answers: AnswerRow[]): ResponseListRow[];
|
|
35
|
+
/** Builds a single response detail with labelled answers. */
|
|
36
|
+
export declare function buildResponseDetail(response: ResponseRow, answers: AnswerRow[], questions: PublishedFormQuestion[]): ResponseDetail;
|
|
37
|
+
/** Renders an answer to a human-readable string, label-mapping choices. */
|
|
38
|
+
export declare function renderAnswer(q: PublishedFormQuestion, a: AnswerRow): string;
|
|
39
|
+
export {};
|
|
40
|
+
//# sourceMappingURL=reporting-aggregations.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reporting-aggregations.d.ts","sourceRoot":"","sources":["../../../../src/lib/dashboard/services/reporting-aggregations.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,EACV,oCAAoC,EACpC,0CAA0C,EAC1C,uBAAuB,EACvB,qBAAqB,EACrB,gBAAgB,EACjB,MAAM,6BAA6B,CAAC;AACrC,OAAO,KAAK,EACV,gBAAgB,EAChB,iBAAiB,EACjB,aAAa,EAGb,UAAU,EACV,eAAe,EACf,cAAc,EAEf,MAAM,2BAA2B,CAAC;AAEnC,KAAK,WAAW,GAAG,oCAAoC,CAAC;AACxD,KAAK,SAAS,GAAG,0CAA0C,CAAC;AA2B5D,0EAA0E;AAC1E,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,uBAAuB,GAAG,qBAAqB,EAAE,CAQtF;AAED,gEAAgE;AAChE,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,gBAAgB,GAAG,aAAa,CAKtE;AAED;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,SAAS,EAAE,WAAW,EAAE,GAAG,gBAAgB,CAsCvE;AAED,sCAAsC;AACtC,wBAAgB,eAAe,CAC7B,SAAS,EAAE,qBAAqB,EAAE,EAClC,OAAO,EAAE,SAAS,EAAE,GACnB,iBAAiB,EAAE,CAqCrB;AAmHD,oDAAoD;AACpD,wBAAgB,WAAW,CACzB,GAAG,EAAE,uBAAuB,EAC5B,OAAO,EAAE,SAAS,EAAE,GACnB,UAAU,EAAE,CAwCd;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAC/B,SAAS,EAAE,WAAW,EAAE,EACxB,OAAO,EAAE,SAAS,EAAE,GACnB,eAAe,EAAE,CAenB;AAED,6DAA6D;AAC7D,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,WAAW,EACrB,OAAO,EAAE,SAAS,EAAE,EACpB,SAAS,EAAE,qBAAqB,EAAE,GACjC,cAAc,CAuBhB;AAED,2EAA2E;AAC3E,wBAAgB,YAAY,CAAC,CAAC,EAAE,qBAAqB,EAAE,CAAC,EAAE,SAAS,GAAG,MAAM,CAwB3E"}
|
|
@@ -0,0 +1,379 @@
|
|
|
1
|
+
/** Max free-text answers surfaced in a breakdown card before truncation. */
|
|
2
|
+
const FREE_TEXT_CAP = 200;
|
|
3
|
+
/** Question types whose answers are visualised as a choice distribution. */
|
|
4
|
+
const CHOICE_TYPES = new Set([
|
|
5
|
+
'SingleChoice',
|
|
6
|
+
'MultiChoice',
|
|
7
|
+
'Dropdown',
|
|
8
|
+
]);
|
|
9
|
+
/** Question types aggregated numerically. */
|
|
10
|
+
const NUMERIC_TYPES = new Set([
|
|
11
|
+
'Number',
|
|
12
|
+
'Rating',
|
|
13
|
+
'NPS',
|
|
14
|
+
]);
|
|
15
|
+
/** Free-text-style types listed verbatim. */
|
|
16
|
+
const TEXT_TYPES = new Set([
|
|
17
|
+
'ShortText',
|
|
18
|
+
'LongText',
|
|
19
|
+
'Email',
|
|
20
|
+
'Phone',
|
|
21
|
+
]);
|
|
22
|
+
/** Flattens a definition's pages into questions in page/display order. */
|
|
23
|
+
export function flattenQuestions(def) {
|
|
24
|
+
const out = [];
|
|
25
|
+
const pages = [...def.pages].sort((a, b) => a.displayOrder - b.displayOrder);
|
|
26
|
+
for (const p of pages) {
|
|
27
|
+
const qs = [...p.questions].sort((a, b) => a.displayOrder - b.displayOrder);
|
|
28
|
+
out.push(...qs);
|
|
29
|
+
}
|
|
30
|
+
return out;
|
|
31
|
+
}
|
|
32
|
+
/** Maps a question type to the breakdown visualisation kind. */
|
|
33
|
+
export function breakdownKindFor(type) {
|
|
34
|
+
if (type === 'YesNo')
|
|
35
|
+
return 'boolean';
|
|
36
|
+
if (CHOICE_TYPES.has(type))
|
|
37
|
+
return 'distribution';
|
|
38
|
+
if (NUMERIC_TYPES.has(type))
|
|
39
|
+
return 'numeric';
|
|
40
|
+
return 'freeText';
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Builds top-line summary stats from response rows.
|
|
44
|
+
*
|
|
45
|
+
* The HEADLINE `totalResponses` counts COMPLETE responses only — a Partial row is an
|
|
46
|
+
* in-progress autosave, not a submitted response, and must never inflate the count a form
|
|
47
|
+
* owner sees. `partialResponses` still surfaces the in-progress count separately, and
|
|
48
|
+
* `completionRate` is complete / (complete + partial) so the drop-off signal is preserved.
|
|
49
|
+
*/
|
|
50
|
+
export function buildSummary(responses) {
|
|
51
|
+
let complete = 0;
|
|
52
|
+
let partial = 0;
|
|
53
|
+
let durationSum = 0;
|
|
54
|
+
let durationCount = 0;
|
|
55
|
+
let lastSubmitted = null;
|
|
56
|
+
for (const r of responses) {
|
|
57
|
+
if (r.Status !== 'Complete') {
|
|
58
|
+
partial++;
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
complete++;
|
|
62
|
+
const submitted = toDate(r.SubmittedAt);
|
|
63
|
+
const started = toDate(r.StartedAt);
|
|
64
|
+
if (submitted && started) {
|
|
65
|
+
const secs = (submitted.getTime() - started.getTime()) / 1000;
|
|
66
|
+
if (secs >= 0) {
|
|
67
|
+
durationSum += secs;
|
|
68
|
+
durationCount++;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
if (submitted && (!lastSubmitted || submitted > lastSubmitted)) {
|
|
72
|
+
lastSubmitted = submitted;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
const started = complete + partial;
|
|
76
|
+
return {
|
|
77
|
+
// Headline count is Complete-only (Partials are in-progress, not responses).
|
|
78
|
+
totalResponses: complete,
|
|
79
|
+
completeResponses: complete,
|
|
80
|
+
partialResponses: partial,
|
|
81
|
+
// Completion rate keeps the started (complete + partial) denominator as the drop-off signal.
|
|
82
|
+
completionRate: started > 0 ? complete / started : 0,
|
|
83
|
+
averageCompletionSeconds: durationCount > 0 ? durationSum / durationCount : null,
|
|
84
|
+
lastSubmittedAt: lastSubmitted,
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
/** Builds per-question breakdowns. */
|
|
88
|
+
export function buildBreakdowns(questions, answers) {
|
|
89
|
+
const byQuestion = groupBy(answers, (a) => a.QuestionID);
|
|
90
|
+
return questions
|
|
91
|
+
.filter((q) => q.type !== 'Statement') // display-only, nothing to aggregate
|
|
92
|
+
.map((q) => {
|
|
93
|
+
const qAnswers = byQuestion.get(q.id) ?? [];
|
|
94
|
+
const kind = breakdownKindFor(q.type);
|
|
95
|
+
const base = {
|
|
96
|
+
questionId: q.id,
|
|
97
|
+
prompt: q.prompt,
|
|
98
|
+
type: q.type,
|
|
99
|
+
kind,
|
|
100
|
+
answeredCount: qAnswers.length,
|
|
101
|
+
buckets: [],
|
|
102
|
+
numeric: null,
|
|
103
|
+
textAnswers: [],
|
|
104
|
+
};
|
|
105
|
+
switch (kind) {
|
|
106
|
+
case 'distribution':
|
|
107
|
+
base.buckets = choiceBuckets(q, qAnswers);
|
|
108
|
+
break;
|
|
109
|
+
case 'boolean':
|
|
110
|
+
base.buckets = booleanBuckets(qAnswers);
|
|
111
|
+
break;
|
|
112
|
+
case 'numeric':
|
|
113
|
+
base.numeric = numericAggregate(q.type, qAnswers);
|
|
114
|
+
break;
|
|
115
|
+
case 'freeText':
|
|
116
|
+
base.textAnswers = qAnswers
|
|
117
|
+
.map((a) => (a.TextValue ?? '').trim())
|
|
118
|
+
.filter((t) => t.length > 0)
|
|
119
|
+
.slice(0, FREE_TEXT_CAP);
|
|
120
|
+
break;
|
|
121
|
+
}
|
|
122
|
+
return base;
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
/** Distribution buckets for choice questions, seeded from the option list. */
|
|
126
|
+
function choiceBuckets(question, answers) {
|
|
127
|
+
const counts = new Map();
|
|
128
|
+
const labelByValue = new Map();
|
|
129
|
+
for (const opt of question.options) {
|
|
130
|
+
counts.set(opt.value, 0);
|
|
131
|
+
labelByValue.set(opt.value, opt.label);
|
|
132
|
+
}
|
|
133
|
+
let totalSelections = 0;
|
|
134
|
+
for (const a of answers) {
|
|
135
|
+
for (const value of extractChoiceValues(a)) {
|
|
136
|
+
counts.set(value, (counts.get(value) ?? 0) + 1);
|
|
137
|
+
if (!labelByValue.has(value)) {
|
|
138
|
+
labelByValue.set(value, value); // value not in option list (legacy/free)
|
|
139
|
+
}
|
|
140
|
+
totalSelections++;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
const buckets = [];
|
|
144
|
+
for (const [value, count] of counts) {
|
|
145
|
+
buckets.push({
|
|
146
|
+
label: labelByValue.get(value) ?? value,
|
|
147
|
+
count,
|
|
148
|
+
fraction: totalSelections > 0 ? count / totalSelections : 0,
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
return buckets.sort((a, b) => b.count - a.count);
|
|
152
|
+
}
|
|
153
|
+
/** Extracts selected values from an answer (single value or multi JSON array). */
|
|
154
|
+
function extractChoiceValues(a) {
|
|
155
|
+
if (a.JSONValue) {
|
|
156
|
+
try {
|
|
157
|
+
const parsed = JSON.parse(a.JSONValue);
|
|
158
|
+
if (Array.isArray(parsed)) {
|
|
159
|
+
return parsed.map((v) => String(v));
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
catch {
|
|
163
|
+
// fall through to TextValue
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
if (a.TextValue !== null && a.TextValue !== undefined && a.TextValue !== '') {
|
|
167
|
+
return [a.TextValue];
|
|
168
|
+
}
|
|
169
|
+
return [];
|
|
170
|
+
}
|
|
171
|
+
/** Yes/No distribution. */
|
|
172
|
+
function booleanBuckets(answers) {
|
|
173
|
+
let yes = 0;
|
|
174
|
+
let no = 0;
|
|
175
|
+
for (const a of answers) {
|
|
176
|
+
if (a.BooleanValue === true)
|
|
177
|
+
yes++;
|
|
178
|
+
else if (a.BooleanValue === false)
|
|
179
|
+
no++;
|
|
180
|
+
}
|
|
181
|
+
const total = yes + no;
|
|
182
|
+
return [
|
|
183
|
+
{ label: 'Yes', count: yes, fraction: total > 0 ? yes / total : 0 },
|
|
184
|
+
{ label: 'No', count: no, fraction: total > 0 ? no / total : 0 },
|
|
185
|
+
];
|
|
186
|
+
}
|
|
187
|
+
/** Numeric aggregate, with NPS scoring when applicable. */
|
|
188
|
+
function numericAggregate(type, answers) {
|
|
189
|
+
const values = [];
|
|
190
|
+
for (const a of answers) {
|
|
191
|
+
if (a.NumericValue !== null && a.NumericValue !== undefined) {
|
|
192
|
+
values.push(a.NumericValue);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
const answered = values.length;
|
|
196
|
+
if (answered === 0) {
|
|
197
|
+
return { answered: 0, min: null, max: null, average: null, npsScore: null };
|
|
198
|
+
}
|
|
199
|
+
let min = values[0];
|
|
200
|
+
let max = values[0];
|
|
201
|
+
let sum = 0;
|
|
202
|
+
for (const v of values) {
|
|
203
|
+
if (v < min)
|
|
204
|
+
min = v;
|
|
205
|
+
if (v > max)
|
|
206
|
+
max = v;
|
|
207
|
+
sum += v;
|
|
208
|
+
}
|
|
209
|
+
const agg = {
|
|
210
|
+
answered,
|
|
211
|
+
min,
|
|
212
|
+
max,
|
|
213
|
+
average: sum / answered,
|
|
214
|
+
npsScore: null,
|
|
215
|
+
};
|
|
216
|
+
if (type === 'NPS') {
|
|
217
|
+
let detractors = 0;
|
|
218
|
+
let passives = 0;
|
|
219
|
+
let promoters = 0;
|
|
220
|
+
for (const v of values) {
|
|
221
|
+
if (v <= 6)
|
|
222
|
+
detractors++;
|
|
223
|
+
else if (v <= 8)
|
|
224
|
+
passives++;
|
|
225
|
+
else
|
|
226
|
+
promoters++;
|
|
227
|
+
}
|
|
228
|
+
agg.npsSegments = { detractors, passives, promoters };
|
|
229
|
+
agg.npsScore = Math.round(((promoters - detractors) / answered) * 100);
|
|
230
|
+
}
|
|
231
|
+
return agg;
|
|
232
|
+
}
|
|
233
|
+
/** Builds the page completion / drop-off funnel. */
|
|
234
|
+
export function buildFunnel(def, answers) {
|
|
235
|
+
const answeredQuestionByResponse = new Map();
|
|
236
|
+
for (const a of answers) {
|
|
237
|
+
let set = answeredQuestionByResponse.get(a.ResponseID);
|
|
238
|
+
if (!set) {
|
|
239
|
+
set = new Set();
|
|
240
|
+
answeredQuestionByResponse.set(a.ResponseID, set);
|
|
241
|
+
}
|
|
242
|
+
set.add(a.QuestionID);
|
|
243
|
+
}
|
|
244
|
+
const pages = [...def.pages].sort((a, b) => a.displayOrder - b.displayOrder);
|
|
245
|
+
const steps = [];
|
|
246
|
+
let firstReached = 0;
|
|
247
|
+
let prevReached = 0;
|
|
248
|
+
for (let i = 0; i < pages.length; i++) {
|
|
249
|
+
const page = pages[i];
|
|
250
|
+
const pageQuestionIds = new Set(page.questions.map((q) => q.id));
|
|
251
|
+
let reached = 0;
|
|
252
|
+
for (const answered of answeredQuestionByResponse.values()) {
|
|
253
|
+
if (hasIntersection(answered, pageQuestionIds)) {
|
|
254
|
+
reached++;
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
if (i === 0) {
|
|
258
|
+
firstReached = reached;
|
|
259
|
+
}
|
|
260
|
+
steps.push({
|
|
261
|
+
pageId: page.id,
|
|
262
|
+
title: page.title || `Page ${i + 1}`,
|
|
263
|
+
displayOrder: page.displayOrder,
|
|
264
|
+
reached,
|
|
265
|
+
retention: firstReached > 0 ? reached / firstReached : 0,
|
|
266
|
+
dropOff: prevReached > 0 ? Math.max(0, (prevReached - reached) / prevReached) : 0,
|
|
267
|
+
});
|
|
268
|
+
prevReached = reached;
|
|
269
|
+
}
|
|
270
|
+
return steps;
|
|
271
|
+
}
|
|
272
|
+
/**
|
|
273
|
+
* Builds the response-list rows. Lists COMPLETE responses only — a Partial is an in-progress
|
|
274
|
+
* autosave, not a submitted response, so it must not appear in the headline response list
|
|
275
|
+
* (it is still reflected in the funnel/drop-off metric, which reads all answers).
|
|
276
|
+
*/
|
|
277
|
+
export function buildResponseRows(responses, answers) {
|
|
278
|
+
const answerCountByResponse = new Map();
|
|
279
|
+
for (const a of answers) {
|
|
280
|
+
answerCountByResponse.set(a.ResponseID, (answerCountByResponse.get(a.ResponseID) ?? 0) + 1);
|
|
281
|
+
}
|
|
282
|
+
return responses
|
|
283
|
+
.filter((r) => r.Status === 'Complete')
|
|
284
|
+
.map((r) => ({
|
|
285
|
+
responseId: r.ID,
|
|
286
|
+
status: r.Status,
|
|
287
|
+
startedAt: toDate(r.StartedAt),
|
|
288
|
+
submittedAt: toDate(r.SubmittedAt),
|
|
289
|
+
respondent: respondentLabel(r),
|
|
290
|
+
answeredCount: answerCountByResponse.get(r.ID) ?? 0,
|
|
291
|
+
}));
|
|
292
|
+
}
|
|
293
|
+
/** Builds a single response detail with labelled answers. */
|
|
294
|
+
export function buildResponseDetail(response, answers, questions) {
|
|
295
|
+
const questionById = new Map(questions.map((q) => [q.id, q]));
|
|
296
|
+
const answerViews = [];
|
|
297
|
+
for (const a of answers) {
|
|
298
|
+
const q = questionById.get(a.QuestionID);
|
|
299
|
+
if (!q || q.type === 'Statement') {
|
|
300
|
+
continue;
|
|
301
|
+
}
|
|
302
|
+
answerViews.push({
|
|
303
|
+
questionId: q.id,
|
|
304
|
+
prompt: q.prompt,
|
|
305
|
+
type: q.type,
|
|
306
|
+
displayValue: renderAnswer(q, a),
|
|
307
|
+
});
|
|
308
|
+
}
|
|
309
|
+
return {
|
|
310
|
+
responseId: response.ID,
|
|
311
|
+
status: response.Status,
|
|
312
|
+
startedAt: toDate(response.StartedAt),
|
|
313
|
+
submittedAt: toDate(response.SubmittedAt),
|
|
314
|
+
respondent: respondentLabel(response),
|
|
315
|
+
answers: answerViews,
|
|
316
|
+
};
|
|
317
|
+
}
|
|
318
|
+
/** Renders an answer to a human-readable string, label-mapping choices. */
|
|
319
|
+
export function renderAnswer(q, a) {
|
|
320
|
+
if (q.type === 'YesNo') {
|
|
321
|
+
return a.BooleanValue === true ? 'Yes' : a.BooleanValue === false ? 'No' : '';
|
|
322
|
+
}
|
|
323
|
+
if (CHOICE_TYPES.has(q.type)) {
|
|
324
|
+
const labelByValue = new Map(q.options.map((o) => [o.value, o.label]));
|
|
325
|
+
return extractChoiceValues(a)
|
|
326
|
+
.map((v) => labelByValue.get(v) ?? v)
|
|
327
|
+
.join(', ');
|
|
328
|
+
}
|
|
329
|
+
if (NUMERIC_TYPES.has(q.type)) {
|
|
330
|
+
return a.NumericValue !== null && a.NumericValue !== undefined ? String(a.NumericValue) : '';
|
|
331
|
+
}
|
|
332
|
+
if (q.type === 'Date' || q.type === 'Time') {
|
|
333
|
+
const d = toDate(a.DateValue);
|
|
334
|
+
return d ? d.toISOString() : '';
|
|
335
|
+
}
|
|
336
|
+
if (q.type === 'FileUpload') {
|
|
337
|
+
return a.FileID ? `File: ${a.FileID}` : '';
|
|
338
|
+
}
|
|
339
|
+
if (TEXT_TYPES.has(q.type)) {
|
|
340
|
+
return a.TextValue ?? '';
|
|
341
|
+
}
|
|
342
|
+
return a.TextValue ?? a.JSONValue ?? '';
|
|
343
|
+
}
|
|
344
|
+
/** Respondent display label: person name, else anonymous session marker. */
|
|
345
|
+
function respondentLabel(r) {
|
|
346
|
+
if (r.RespondentPerson)
|
|
347
|
+
return r.RespondentPerson;
|
|
348
|
+
if (r.AnonymousSessionID)
|
|
349
|
+
return 'Anonymous';
|
|
350
|
+
return 'Anonymous';
|
|
351
|
+
}
|
|
352
|
+
/** Coerces a possibly-string datetime into a Date, or null. */
|
|
353
|
+
function toDate(value) {
|
|
354
|
+
if (value === null || value === undefined)
|
|
355
|
+
return null;
|
|
356
|
+
const d = value instanceof Date ? value : new Date(value);
|
|
357
|
+
return isNaN(d.getTime()) ? null : d;
|
|
358
|
+
}
|
|
359
|
+
function groupBy(items, key) {
|
|
360
|
+
const map = new Map();
|
|
361
|
+
for (const item of items) {
|
|
362
|
+
const k = key(item);
|
|
363
|
+
const arr = map.get(k);
|
|
364
|
+
if (arr)
|
|
365
|
+
arr.push(item);
|
|
366
|
+
else
|
|
367
|
+
map.set(k, [item]);
|
|
368
|
+
}
|
|
369
|
+
return map;
|
|
370
|
+
}
|
|
371
|
+
function hasIntersection(a, b) {
|
|
372
|
+
const [small, large] = a.size <= b.size ? [a, b] : [b, a];
|
|
373
|
+
for (const v of small) {
|
|
374
|
+
if (large.has(v))
|
|
375
|
+
return true;
|
|
376
|
+
}
|
|
377
|
+
return false;
|
|
378
|
+
}
|
|
379
|
+
//# sourceMappingURL=reporting-aggregations.js.map
|