((subscriber) => {\n request\n .then((response) => {\n subscriber.next(response.data);\n subscriber.complete();\n })\n .catch((err: Error) => {\n subscriber.error(err);\n subscriber.complete();\n });\n });\n }\n}\n","\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nimport { Component, Vue, Prop } from 'vue-property-decorator';\nimport VueRecaptcha from 'vue-recaptcha';\nimport { NextType, Answer } from '@/models/answer';\nimport { TreeNode } from '@/models/treenode';\nimport { Observable, fromEvent } from 'rxjs';\nimport { first, tap, catchError, finalize } from 'rxjs/operators';\nimport Rxios from '@/vendor/rxios';\n\n@Component({\n components: {\n VueRecaptcha\n }\n})\nexport default class BreadcrumbComponent extends Vue {\n public isExpanded: boolean = false;\n public showSendMessage: boolean = false;\n public isCaptchaValid: boolean = false;\n public recaptchaResponse: string = '';\n public isSendingMail: boolean = false;\n public isSendSuccess: boolean = false;\n public isSendError: boolean = false;\n public isBusy: boolean = false;\n public capchaErrorMessage: string = '';\n public emailFrom: string = '';\n public emailTo: string = '';\n public sendMailResponse: string = '';\n\n private http: Rxios = new Rxios({\n // all regular axios request configuration options are valid here\n // check https://github.com/axios/axios#request-config\n baseURL: process.env.VUE_APP_API_ENDPOINT,\n headers: {\n 'Accept': 'application/json',\n 'Content-Type': 'application/json',\n },\n });\n\n public get currentTreeNode(): TreeNode {\n return this.$store.getters.currentTreeNode;\n }\n\n public get currentAnswers(): { [treeNodeId: string]: Answer; } {\n return this.$store.getters.currentAnswers;\n }\n\n public get navigation(): string[] {\n return this.$store.getters.navigation;\n }\n\n public get recaptchaSiteKey(): string {\n return this.$store.getters.recaptchaSiteKey;\n }\n\n public select(answer: Answer, target: any, nodeID: string): void {\n const test = target.parentElement as HTMLElement;\n\n if (test.tagName === 'OBJECT') {\n return;\n }\n this.isExpanded = false;\n this.showSendMessage = false;\n this.$store.dispatch('goToNode', nodeID);\n }\n\n public togglePathVisibility() {\n this.isExpanded = !this.isExpanded;\n\n if (!this.isExpanded) {\n this.showSendMessage = false;\n this.isSendSuccess = false;\n this.isSendError = false;\n }\n }\n\n // TODO: Remove this and fetch HTML from API\n public get getHtmlForPrint(): string {\n let html = '' + window.location.href + '';\n let count = 1;\n\n for (const index in this.currentAnswers) {\n if (this.currentAnswers.hasOwnProperty(index)) {\n const answer = this.currentAnswers[index];\n if (index === this.currentTreeNode.id) {\n html = html\n + ''\n + count\n + '. Spørgsmål: '\n + answer.question\n + '
'\n + answer.answer\n + '
';\n } else {\n html = html\n + ''\n + count\n + '. Spørgsmål: '\n + answer.question\n + '
'\n + answer.answer\n + '
';\n }\n count++;\n }\n }\n\n return html;\n }\n\n public onRecaptchaVerified(response: string): void {\n this.recaptchaResponse = response;\n this.isCaptchaValid = response.length > 0;\n }\n\n public sendMail(): void {\n if (!this.isCaptchaValid) {\n this.capchaErrorMessage = 'Verificer at du er et menneske';\n } else {\n this.capchaErrorMessage = '';\n const fromMail = this.emailFrom;\n const toMail = this.emailTo;\n\n this.http.post('/share/ShareDecisionTree', {\n decisionTreeId: this.$store.getters.model.id,\n receiver: toMail,\n sender: fromMail,\n recaptcha: this.recaptchaResponse,\n answers: Object.keys(this.currentAnswers).map(a => ({\n answerId: this.currentAnswers[a].id,\n referencedQuestion: this.currentAnswers[a].question\n } as any)),\n currentTreeNode: this.currentTreeNode.id,\n language: 'da'\n }).pipe(\n first(),\n tap(_ => this.isBusy = true),\n tap(response => {\n // TODO: These timeouts...\n setTimeout(() => {\n this.isSendSuccess = true;\n }, 1000);\n this.sendMailResponse = 'Historikken er er sendt';\n const self = this;\n setTimeout(() => {\n self.isSendSuccess = false;\n self.sendMailResponse = '';\n self.showSendMessage = false;\n this.emailTo = '';\n }, 4000);\n }),\n catchError((err, caught) => {\n // TODO: These timeouts...\n setTimeout(() => {\n this.isSendError = true;\n }, 1000);\n this.sendMailResponse = 'Noget gik galt - prøv igen senere, eller kontakt lægemiddelstyrelsen';\n const self = this;\n setTimeout(() => {\n self.isSendError = false;\n self.sendMailResponse = '';\n self.showSendMessage = false;\n }, 4000);\n\n return err;\n }),\n finalize(() => this.isBusy = false)\n ).subscribe();\n }\n }\n\n public print() {\n const printWindow = window.open('', 'Print', 'height=600,width=800');\n\n if (printWindow != null) {\n printWindow.document.write('Print');\n printWindow.document.write('');\n printWindow.document.write(this.getHtmlForPrint);\n printWindow.document.write('');\n\n printWindow.document.close();\n printWindow.focus();\n printWindow.print();\n printWindow.close();\n }\n }\n}\n\n","import mod from \"-!../../node_modules/cache-loader/dist/cjs.js??ref--13-0!../../node_modules/thread-loader/dist/cjs.js!../../node_modules/babel-loader/lib/index.js!../../node_modules/ts-loader/index.js??ref--13-3!../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../node_modules/vue-loader/lib/index.js??vue-loader-options!./Breadcrumb.vue?vue&type=script&lang=ts&\"; export default mod; export * from \"-!../../node_modules/cache-loader/dist/cjs.js??ref--13-0!../../node_modules/thread-loader/dist/cjs.js!../../node_modules/babel-loader/lib/index.js!../../node_modules/ts-loader/index.js??ref--13-3!../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../node_modules/vue-loader/lib/index.js??vue-loader-options!./Breadcrumb.vue?vue&type=script&lang=ts&\"","import { render, staticRenderFns } from \"./Breadcrumb.vue?vue&type=template&id=ff5066e2&scoped=true&\"\nimport script from \"./Breadcrumb.vue?vue&type=script&lang=ts&\"\nexport * from \"./Breadcrumb.vue?vue&type=script&lang=ts&\"\nimport style0 from \"./Breadcrumb.vue?vue&type=style&index=0&id=ff5066e2&lang=less&scoped=true&\"\n\n\n/* normalize component */\nimport normalizer from \"!../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n \"ff5066e2\",\n null\n \n)\n\nexport default component.exports","\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nimport { Component, Prop, Vue } from 'vue-property-decorator';\nimport SpinnerComponent from '@/components/Spinner.vue';\nimport PretextComponent from '@/components/Pretext.vue';\nimport TreeNodeComponent from '@/components/TreeNode.vue';\nimport { DecisionTree } from '@/models/decisiontree';\nimport { TreeNode } from '@/models/treenode';\nimport NavigationComponent from '@/components/Navigation.vue';\nimport BreadcrumbComponent from '@/components/Breadcrumb.vue';\nimport store from '@/store';\n\n@Component({\n components: {\n SpinnerComponent,\n PretextComponent,\n TreeNodeComponent,\n NavigationComponent,\n BreadcrumbComponent\n }\n})\nexport default class App extends Vue {\n\n public mounted() {\n this.$store.commit('setIsBusy', false);\n }\n\n public get error(): string {\n return this.$store.getters.error;\n }\n\n public get isBusy() {\n return this.$store.getters.isBusy;\n }\n\n public get isNavigating() {\n return this.$store.getters.isNavigating;\n }\n\n public get treeNode(): TreeNode {\n return this.$store.getters.currentTreeNode;\n }\n\n public get model(): DecisionTree {\n return this.$store.getters.model;\n }\n}\n","import mod from \"-!../node_modules/cache-loader/dist/cjs.js??ref--13-0!../node_modules/thread-loader/dist/cjs.js!../node_modules/babel-loader/lib/index.js!../node_modules/ts-loader/index.js??ref--13-3!../node_modules/cache-loader/dist/cjs.js??ref--0-0!../node_modules/vue-loader/lib/index.js??vue-loader-options!./App.vue?vue&type=script&lang=ts&\"; export default mod; export * from \"-!../node_modules/cache-loader/dist/cjs.js??ref--13-0!../node_modules/thread-loader/dist/cjs.js!../node_modules/babel-loader/lib/index.js!../node_modules/ts-loader/index.js??ref--13-3!../node_modules/cache-loader/dist/cjs.js??ref--0-0!../node_modules/vue-loader/lib/index.js??vue-loader-options!./App.vue?vue&type=script&lang=ts&\"","import { render, staticRenderFns } from \"./App.vue?vue&type=template&id=42008bb6&scoped=true&\"\nimport script from \"./App.vue?vue&type=script&lang=ts&\"\nexport * from \"./App.vue?vue&type=script&lang=ts&\"\nimport style0 from \"./App.vue?vue&type=style&index=0&id=42008bb6&lang=less&scoped=true&\"\n\n\n/* normalize component */\nimport normalizer from \"!../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n \"42008bb6\",\n null\n \n)\n\nexport default component.exports","import Rxios from '../vendor/rxios';\nimport { getDataProperty, queryParams } from './utils';\nimport { Observable } from 'rxjs';\n\nexport default class ApiService {\n private http: Rxios;\n private formAntiForgeryToken: string;\n private sitecoreId: string;\n private sitecoreLang: string;\n\n // Query parameters\n private subscriptionToken: string;\n private email: string;\n private language: string;\n\n constructor() {\n this.formAntiForgeryToken = getDataProperty('data-antiforgery-token');\n this.sitecoreId = getDataProperty('data-id');\n this.sitecoreLang = getDataProperty('data-lang');\n\n this.subscriptionToken = queryParams.token;\n this.email = queryParams.email;\n this.language = queryParams.language;\n\n this.http = new Rxios({\n baseURL: process.env.VUE_APP_API_ENDPOINT,\n headers: {\n 'RequestVerificationToken': this.formAntiForgeryToken,\n 'SubscriptionVerificationToken': `${this.email}:${this.language}:${this.subscriptionToken}`,\n 'SitecoreId': this.sitecoreId,\n 'SitecoreLanguage': this.sitecoreLang,\n 'Accept': 'application/json',\n 'Content-Type': 'application/json',\n },\n });\n }\n\n public get(action: string, queryParams?: object): Observable {\n return this.http.get(`/${action}`, queryParams);\n }\n\n public post(\n action: string,\n body: object,\n queryParams?: object,\n ): Observable {\n return this.http.post(`/${action}`, body, queryParams);\n }\n\n public patch(\n url: string,\n body: object,\n queryParams?: object,\n ): Observable {\n return this.http.patch(url, body, queryParams);\n }\n\n public delete(url: string, queryParams?: object): Observable {\n return this.http.delete(url, queryParams);\n }\n}\n","import { finalize } from 'rxjs/operators';\nimport Vue from 'vue';\nimport Vuex from 'vuex';\nimport { GetTreeNode } from './commands/get.treenode';\nimport { Answer } from './models/answer';\nimport { DecisionTree } from './models/decisiontree';\nimport { TreeNode } from './models/treenode';\nimport ApiService from './services/api.service';\nimport { getDataProperty } from './services/utils';\n\nVue.use(Vuex);\n\nexport default new Vuex.Store({\n getters: {\n currentTreeNode: state => state.currentTreeNode,\n currentAnswers: state => state.currentAnswers as { [treeNodeId: string]: Answer; },\n currentAnswer: state => state.currentAnswers[state.currentTreeNode.id],\n isBusy: state => state.isBusy,\n isNavigating: state => state.isNavigating,\n model: state => state.model,\n error: state => state.error,\n navigation: state => state.navigation,\n recaptchaSiteKey: state => state.recaptchaSiteKey\n },\n state: {\n isBusy: true,\n isNavigating: false,\n apiService: new ApiService(),\n error: '' as string,\n currentTreeNode: undefined as unknown as TreeNode,\n currentAnswers: {} as { [treeNodeId: string]: Answer; },\n model: JSON.parse(getDataProperty('data-model')) as DecisionTree,\n recaptchaSiteKey: getDataProperty('data-recaptcha-sitekey') as string,\n navigation: [] as string[]\n },\n mutations: {\n setTreeNode: (state, content: TreeNode) => {\n state.currentTreeNode = content;\n },\n setIsBusy: (state, isBusy: boolean) => {\n state.isBusy = isBusy;\n },\n setIsNavigating: (state, isNavigating: boolean) => {\n state.isNavigating = isNavigating;\n },\n setError: (state, message?: string) => {\n state.error = message ? message : 'Der skete desværre en fejl. Prøv igen om lidt.';\n },\n clearError: (state) => {\n state.error = '';\n },\n pushNavigation: (state, treeNodeId: string) => {\n state.navigation.push(treeNodeId);\n },\n popNavigation: (state) => {\n state.navigation.pop();\n },\n selectCurrentAnswer: (state, answer: Answer) => {\n const currentNodeAnswer = state.currentAnswers[state.currentTreeNode.id];\n answer.question = state.currentTreeNode.title;\n\n if (currentNodeAnswer && currentNodeAnswer.id !== answer.id) {\n // Tree node already has a different answer here\n // Find the next node that the answer points to\n let nextNodeId = currentNodeAnswer.next.nextId;\n Vue.delete(state.currentAnswers, nextNodeId);\n\n // Kill the entire string of answers (forget previous branch of navigation) that follow it\n while (true) {\n const nextAnswer = state.currentAnswers[nextNodeId];\n\n if (!nextAnswer) {\n break;\n } else {\n Vue.delete(state.currentAnswers, nextNodeId);\n nextNodeId = nextAnswer.next.nextId;\n }\n }\n }\n\n // Set the answer for the current tree node\n Vue.set(state.currentAnswers, state.currentTreeNode.id, answer);\n }\n },\n actions: {\n goToPreviousNode: (context) => {\n context.commit('popNavigation');\n if (context.getters.navigation.length < 1) {\n context.dispatch('goToStart');\n } else {\n context.dispatch('goToNode', context.getters.navigation[context.getters.navigation.length - 1]);\n }\n },\n scrollTop: (context) => {\n const element = document.querySelector('.decisiontree') as HTMLElement;\n const dims = element.getBoundingClientRect();\n window.scrollTo(window.scrollX, dims.top - 20);\n },\n goToNode: (context, treeNodeId: string) => {\n context.commit('clearError');\n context.commit('setIsNavigating', true);\n\n setTimeout(() => {\n context.commit('setIsBusy', true);\n const command = {\n treeNodeId,\n includeAnswers: true\n } as GetTreeNode;\n\n context.state.apiService\n .get('treenodes', command)\n .pipe(\n finalize(() => {\n context.commit('setIsBusy', false);\n context.commit('setIsNavigating', false);\n context.dispatch('scrollTop');\n })\n )\n .subscribe(\n (treeNode) => context.commit('setTreeNode', treeNode),\n (err: any) => context.commit('setError')\n );\n },\n 300);\n },\n goToStart: (context) => {\n context.commit('setIsNavigating', true);\n context.commit('setTreeNode', undefined);\n\n setTimeout(() => {\n context.commit('setIsNavigating', false);\n context.dispatch('scrollTop');\n },\n 150);\n },\n startDecisionTree: (context) => {\n context.commit('pushNavigation', context.state.model.startNodeId);\n context.dispatch('goToNode', context.state.model.startNodeId);\n }\n }\n});\n","/* tslint:disable:no-console */\n\nimport { register } from 'register-service-worker';\n\nif (process.env.NODE_ENV === 'production') {\n register(`${process.env.BASE_URL}service-worker.js`, {\n ready() {\n console.log(\n 'App is being served from cache by a service worker.\\n' +\n 'For more details, visit https://goo.gl/AFskqB',\n );\n },\n registered() {\n console.log('Service worker has been registered.');\n },\n cached() {\n console.log('Content has been cached for offline use.');\n },\n updatefound() {\n console.log('New content is downloading.');\n },\n updated() {\n console.log('New content is available; please refresh.');\n },\n offline() {\n console.log('No internet connection found. App is running in offline mode.');\n },\n error(error) {\n console.error('Error during service worker registration:', error);\n },\n });\n}\n","import Vue from 'vue';\nimport App from './App.vue';\nimport store from './store';\nimport './registerServiceWorker';\n\nVue.config.productionTip = false;\n\nif (!Array.prototype.forEach) {\n Array.prototype.forEach = function(fn, scope) {\n for (let i = 0, len = this.length; i < len; ++i) {\n fn.call(scope, this[i], i, this);\n }\n };\n}\n\nif (!NodeList.prototype.forEach) {\n NodeList.prototype.forEach = function(fn, scope) {\n for (let i = 0, len = this.length; i < len; ++i) {\n fn.call(scope, this[i], i, this);\n }\n };\n}\n\nnew Vue({\n store,\n render: (h) => h(App),\n}).$mount('#decisiontree-app');\n"],"sourceRoot":""}