Skip to content

Commit c55d420

Browse files
authored
ZARS-980 redirect to feasibility portal (#210)
1 parent 38e361a commit c55d420

File tree

5 files changed

+67
-3
lines changed

5 files changed

+67
-3
lines changed

src/locales/de.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -809,7 +809,8 @@
809809
"registerProjectModalDescription": "Es wird eine Kopie dieses Projekts als Registrierungsformular erstellt. Sie können dann die Veröffentlichungsdetails ausfüllen und es im FDPG-Register veröffentlichen. Das Originalprojekt bleibt unverändert.",
810810
"registerProject": "Projekt registrieren",
811811
"projectCopiedForRegistration": "Projekt erfolgreich kopiert. Bitte füllen Sie die Registrierungsdetails aus.",
812-
"projectAssignee": "Abtretungsempfänger:in"
812+
"projectAssignee": "Abtretungsempfänger:in",
813+
"redirectToFeasibilityPortal": "Datenportal"
813814
},
814815
"roles": {
815816
"FdpgMember": "FDPG Mitarbeiter",

src/locales/en.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -809,7 +809,8 @@
809809
"registerProjectModalDescription": "This will create a copy of this project as a registration form. You can then fill in publication details and publish it to the FDPG register. The original project will remain unchanged.",
810810
"registerProject": "Register Project",
811811
"projectCopiedForRegistration": "Project copied successfully. Please fill in the registration details.",
812-
"projectAssignee": "Project assignee"
812+
"projectAssignee": "Project assignee",
813+
"redirectToFeasibilityPortal": "Feasibility Portal"
813814
},
814815
"roles": {
815816
"FdpgMember": "FDPG Employee",

src/pages/Proposals/Casesohort/ReviewMemberCohortSelection.vue

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,20 @@
2525
</template>
2626
</el-table-column>
2727

28+
<el-table-column v-if="canRedirectToFeasibilityPortal" :label="t('proposal.redirectToFeasibilityPortal')">
29+
<template #default="scope">
30+
<el-button
31+
v-if="scope.row.feasibilityQueryId"
32+
type="primary"
33+
link
34+
@click="redirectToFeasibilityPortal(scope.row.feasibilityQueryId)"
35+
data-test-id="redirectToFeasibilityPortal"
36+
>
37+
{{ t('proposal.redirectToFeasibilityPortal') }}
38+
</el-button>
39+
</template>
40+
</el-table-column>
41+
2842
<el-table-column :label="t('proposal.viewQuery')">
2943
<template #default="scope">
3044
<el-button
@@ -79,14 +93,17 @@
7993
</template>
8094

8195
<script setup lang="ts">
82-
import { ref } from 'vue'
96+
import { computed, ref } from 'vue'
8397
import { useI18n } from 'vue-i18n'
8498
import type { FormInstance, UploadFile } from 'element-plus'
8599
import type { ISelectedCohort } from '@/types/proposal.types'
86100
import { useVModel } from '@vueuse/core'
87101
import ManualCohortDialog from './ManualCohortDialog.vue'
88102
import useNotifications from '@/composables/use-notifications'
89103
import { useProposalStore } from '@/stores/proposal/proposal.store'
104+
import { useAuthStore } from '@/stores/auth/auth.store'
105+
import { useFeasibilityStore } from '@/stores/feasibility.store'
106+
import { Role } from '@/types/oidc.types'
90107
91108
const { t } = useI18n()
92109
const { showErrorMessage } = useNotifications()
@@ -104,6 +121,42 @@ const props = defineProps({
104121
},
105122
})
106123
124+
const authStore = useAuthStore()
125+
const feasibilityStore = useFeasibilityStore()
126+
127+
const canRedirectToFeasibilityPortal = computed(() =>
128+
new Set([Role.FdpgMember, Role.DizMember]).has(authStore.singleKnownRole ?? Role.Admin),
129+
)
130+
131+
const redirectToFeasibilityPortal = async (queryId: number): Promise<void> => {
132+
try {
133+
const url = await feasibilityStore.getRedirectUrl(queryId)
134+
135+
if (!isValidHttpUrl(url)) {
136+
throw new Error(`Invalid redirect URL received: "${url}"`)
137+
}
138+
139+
window.open(url, '_blank')
140+
} catch (error) {
141+
console.error('Redirect to Feasibility Portal failed:', error)
142+
showErrorMessage()
143+
}
144+
}
145+
146+
const isValidHttpUrl = (urlString: string): boolean => {
147+
if (!urlString) {
148+
return false
149+
}
150+
151+
try {
152+
const url = new URL(urlString)
153+
return url.protocol === 'http:' || url.protocol === 'https:'
154+
} catch (e) {
155+
console.error(`invalid or empty URL: "${urlString}"`)
156+
return false
157+
}
158+
}
159+
107160
const emit = defineEmits(['update:modelValue', 'update:uploads', 'addCohort', 'removeCohort'])
108161
109162
const cohorts = useVModel(props, 'modelValue', emit)

src/services/feasibility/feasibility.service.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,9 @@ export class FeasibilityService {
99
const response = await this.apiClient.get(this.basePath)
1010
return response.data
1111
}
12+
13+
async getRedirectUrl(queryId: number): Promise<string> {
14+
const response = await this.apiClient.get(`${this.basePath}/redirect/${queryId}`)
15+
return response.data.redirectUrl
16+
}
1217
}

src/stores/feasibility.store.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,5 +17,9 @@ export const useFeasibilityStore = defineStore('Feasibility', {
1717
async getAll(): Promise<void> {
1818
this.feasibilityQueries = await this.apiService.getAll()
1919
},
20+
21+
async getRedirectUrl(queryId): Promise<string> {
22+
return await this.apiService.getRedirectUrl(queryId)
23+
},
2024
},
2125
})

0 commit comments

Comments
 (0)