Skip to content

Commit a994645

Browse files
Merge pull request #8615 from christianbeeznest/feature/survey-state-organization
Survey: Organize state providers and processors
2 parents 2b67a62 + bf71550 commit a994645

50 files changed

Lines changed: 1282 additions & 148 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

assets/vue/App.vue

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,12 @@ const layout = computed(() => {
242242
return EmptyLayout
243243
}
244244
245-
if ((qp.has("lp_id") && "view" === qp.get("action")) || (qp.has("origin") && "learnpath" === qp.get("origin"))) {
245+
const lpAction = String(qp.get("action") || "").toLowerCase()
246+
const isLearningPathPlayerContext =
247+
qp.has("lp_id") &&
248+
("view" === lpAction || "1" === qp.get("embedded") || "true" === String(qp.get("isStudentView") || ""))
249+
250+
if (isLearningPathPlayerContext) {
246251
return EmptyLayout
247252
}
248253

assets/vue/composables/useTopbarLoggedIn.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -304,8 +304,11 @@ export function useTopbarLoggedIn(props) {
304304
if (resolvedRoute?.href) {
305305
return resolvedRoute.href
306306
}
307-
} catch {}
308-
return "/main/survey/pending.php"
307+
} catch (error) {
308+
console.error("Could not resolve pending surveys route", error)
309+
}
310+
311+
return "/survey/pending"
309312
})
310313

311314
const myServicesUrl = computed(() => {

assets/vue/router/index.js

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -466,6 +466,16 @@ const router = createRouter({
466466
component: MySessionListUpcoming,
467467
meta: { requiresAuth: true },
468468
},
469+
{
470+
path: "/survey/pending",
471+
name: "SurveyPending",
472+
component: () => import("../views/survey/SurveyPendingView.vue"),
473+
meta: {
474+
requiresAuth: true,
475+
showBreadcrumb: true,
476+
breadcrumb: "Pending surveys",
477+
},
478+
},
469479
fileManagerRoutes,
470480
socialNetworkRoutes,
471481
catalogue,
@@ -584,12 +594,13 @@ router.beforeEach(async (to, from, next) => {
584594
}
585595

586596
// Determine what the route requires
597+
const allowsAnonymousAccess = to.matched.some((record) => record.meta?.allowAnonymousAccess === true)
587598
const needsAuth = to.matched.some((record) => record.meta?.requiresAuth === true)
588599
const wantsAdmin = to.matched.some((record) => record.meta?.requiresAdmin === true)
589600
const wantsSessionAdmin = to.matched.some((record) => record.meta?.requiresSessionAdmin === true)
590601
const wantsHR = to.matched.some((record) => record.meta?.requiresHR === true)
591602

592-
const mustBeLogged = needsAuth || wantsAdmin || wantsSessionAdmin || wantsHR
603+
const mustBeLogged = !allowsAnonymousAccess && (needsAuth || wantsAdmin || wantsSessionAdmin || wantsHR)
593604

594605
if (mustBeLogged && !securityStore.isLoading) {
595606
await securityStore.checkSession()

assets/vue/router/survey.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ export default {
8080
{
8181
name: "SurveyAnswer",
8282
path: ":surveyId/answer",
83-
meta: { breadcrumb: "Answer survey" },
83+
meta: { breadcrumb: "Answer survey", allowAnonymousAccess: true },
8484
component: () => import("../views/survey/SurveyAnswerView.vue"),
8585
},
8686
],

assets/vue/services/surveyService.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@ export default {
3636
return await baseService.get("/api/survey/list", cleanParams(params), surveyRequestConfig())
3737
},
3838

39+
async getPendingSurveys(params = {}) {
40+
return await baseService.get("/api/survey/pending", cleanParams(params), surveyRequestConfig())
41+
},
42+
3943
async getSurveyConfiguration(params = {}, surveyId = null) {
4044
const endpoint = surveyId ? `/api/survey/configuration/${surveyId}` : "/api/survey/configuration"
4145

assets/vue/views/survey/SurveyAnswerView.vue

Lines changed: 47 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
<div class="flex flex-wrap items-center justify-end gap-2">
1717
<BaseButton
18+
v-if="showBackToSurveyList"
1819
:label="t('Back to survey list')"
1920
:route="buildListRoute()"
2021
icon="back"
@@ -418,6 +419,28 @@ const currentPageIndex = ref(0)
418419
419420
const surveyId = computed(() => Number(route.params.surveyId || 0))
420421
const previewMode = computed(() => route.name === "SurveyPreview" || route.query.preview === "1")
422+
const isLearningPathContext = computed(() => {
423+
const origin = String(getQueryValue(route.query.origin) || "")
424+
const returnToLp = String(getQueryValue(route.query.returnToLp) || "")
425+
426+
return (
427+
origin === "learnpath" ||
428+
returnToLp === "1" ||
429+
Boolean(getQueryValue(route.query.lp_id)) ||
430+
Boolean(getQueryValue(route.query.lpItemId || route.query.lp_item_id))
431+
)
432+
})
433+
const isPublicAnswerContext = computed(() => {
434+
return (
435+
Boolean(getQueryValue(route.query.invitationCode || route.query.invitationcode)) ||
436+
Boolean(getQueryValue(route.query.publicCid)) ||
437+
Boolean(getQueryValue(route.query.publicSid)) ||
438+
Boolean(getQueryValue(route.query.publicGid))
439+
)
440+
})
441+
const showBackToSurveyList = computed(() => {
442+
return !isLearningPathContext.value && !isPublicAnswerContext.value
443+
})
421444
const canInteract = computed(() => previewMode.value || canSubmit.value)
422445
const totalPages = computed(() => Math.max(1, pages.value.length))
423446
const currentQuestionIds = computed(() => pages.value[currentPageIndex.value] || [])
@@ -426,13 +449,26 @@ const currentVisibleQuestions = computed(() => currentQuestions.value.filter((qu
426449
const canGoNext = computed(() => currentPageIndex.value < totalPages.value - 1)
427450
const canGoBack = computed(() => settings.value.backwardsEnabled && currentPageIndex.value > 0)
428451
452+
function getQueryValue(value) {
453+
return Array.isArray(value) ? value[0] : value
454+
}
455+
429456
function getContextParams() {
430457
return {
431-
cid: route.query.cid,
432-
sid: route.query.sid,
433-
gid: route.query.gid,
434-
invitationCode: route.query.invitationCode || route.query.invitationcode,
435-
lpItemId: route.query.lpItemId || route.query.lp_item_id,
458+
cid: getQueryValue(route.query.cid),
459+
sid: getQueryValue(route.query.sid),
460+
gid: getQueryValue(route.query.gid),
461+
publicCid: getQueryValue(route.query.publicCid),
462+
publicSid: getQueryValue(route.query.publicSid),
463+
publicGid: getQueryValue(route.query.publicGid),
464+
invitationCode: getQueryValue(route.query.invitationCode || route.query.invitationcode),
465+
lpItemId: getQueryValue(route.query.lpItemId || route.query.lp_item_id),
466+
lp_id: getQueryValue(route.query.lp_id),
467+
origin: getQueryValue(route.query.origin),
468+
type: getQueryValue(route.query.type),
469+
returnToLp: getQueryValue(route.query.returnToLp),
470+
embedded: getQueryValue(route.query.embedded),
471+
isStudentView: getQueryValue(route.query.isStudentView),
436472
preview: previewMode.value ? 1 : undefined,
437473
}
438474
}
@@ -442,9 +478,9 @@ function buildListRoute() {
442478
name: "SurveyList",
443479
params: { node: route.params.node },
444480
query: {
445-
cid: route.query.cid,
446-
sid: route.query.sid,
447-
gid: route.query.gid,
481+
...getContextParams(),
482+
invitationCode: undefined,
483+
preview: undefined,
448484
},
449485
}
450486
}
@@ -457,9 +493,9 @@ function buildConfigureRoute() {
457493
surveyId: surveyId.value,
458494
},
459495
query: {
460-
cid: route.query.cid,
461-
sid: route.query.sid,
462-
gid: route.query.gid,
496+
...getContextParams(),
497+
invitationCode: undefined,
498+
preview: undefined,
463499
},
464500
}
465501
}

assets/vue/views/survey/SurveyConfigurationView.vue

Lines changed: 94 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222

2323
<div class="flex flex-wrap items-center gap-2">
2424
<BaseButton
25+
v-if="!isLearningPathContext"
2526
:label="t('Back to survey list')"
2627
:route="buildListRoute()"
2728
icon="back"
@@ -362,6 +363,14 @@
362363
class="flex flex-col-reverse gap-3 rounded-2xl border border-gray-20 bg-white p-6 shadow-sm md:flex-row md:items-center md:justify-end"
363364
>
364365
<BaseButton
366+
v-if="isLearningPathContext"
367+
:label="t('Cancel')"
368+
icon="close"
369+
type="black"
370+
@click="goToLearningPathAddItem"
371+
/>
372+
<BaseButton
373+
v-else
365374
:label="t('Cancel')"
366375
:route="buildListRoute()"
367376
icon="close"
@@ -467,14 +476,89 @@ function createEmptyForm() {
467476
}
468477
}
469478
470-
function getContextParams() {
479+
function getContextParams(extra = {}) {
480+
return cleanQueryParams({
481+
cid: getQueryValue(route.query.cid),
482+
sid: getQueryValue(route.query.sid),
483+
gid: getQueryValue(route.query.gid),
484+
origin: getQueryValue(route.query.origin),
485+
lp_id: getQueryValue(route.query.lp_id),
486+
lpItemId: getQueryValue(route.query.lpItemId || route.query.lp_item_id),
487+
type: getQueryValue(route.query.type),
488+
returnToLp: getQueryValue(route.query.returnToLp),
489+
isStudentView: getQueryValue(route.query.isStudentView),
490+
...extra,
491+
})
492+
}
493+
494+
function getQueryValue(value) {
495+
if (Array.isArray(value)) {
496+
return value[0] || ""
497+
}
498+
499+
return value || ""
500+
}
501+
502+
function cleanQueryParams(params = {}) {
503+
const cleanParams = {}
504+
505+
for (const [key, value] of Object.entries(params)) {
506+
if (value !== undefined && value !== null && String(value) !== "") {
507+
cleanParams[key] = value
508+
}
509+
}
510+
511+
return cleanParams
512+
}
513+
514+
const learningPathId = computed(() => Number(getQueryValue(route.query.lp_id) || 0))
515+
516+
const isLearningPathContext = computed(() => {
517+
return getQueryValue(route.query.origin) === "learnpath" && learningPathId.value > 0
518+
})
519+
520+
function buildLearningPathQuery(extra = {}) {
521+
const query = new URLSearchParams()
522+
523+
query.set("action", extra.action || "add_item")
524+
query.set("type", extra.type || "step")
525+
query.set("lp_id", String(learningPathId.value))
526+
527+
for (const key of ["cid", "sid", "gid"]) {
528+
const value = getQueryValue(route.query[key])
529+
530+
if (String(value) !== "") {
531+
query.set(key, String(value))
532+
}
533+
}
534+
535+
query.set("isStudentView", "false")
536+
537+
if (extra.surveyId) {
538+
query.set("survey_id", String(extra.surveyId))
539+
}
540+
541+
return query.toString()
542+
}
543+
544+
function buildLearningPathAddItemUrl() {
545+
return `/main/lp/lp_controller.php?${buildLearningPathQuery()}`
546+
}
547+
548+
function buildLearningPathQuestionsRoute(surveyId) {
471549
return {
472-
cid: route.query.cid,
473-
sid: route.query.sid,
474-
gid: route.query.gid,
550+
name: "SurveyQuestions",
551+
params: {
552+
node: route.params.node,
553+
surveyId,
554+
},
555+
query: getContextParams({ lpItemId: undefined }),
475556
}
476557
}
477558
559+
function goToLearningPathAddItem() {
560+
window.location.href = buildLearningPathAddItemUrl()
561+
}
478562
479563
function buildQuestionsRoute() {
480564
return {
@@ -654,6 +738,12 @@ async function submitForm() {
654738
csrfToken.value = saved.csrfToken || csrfToken.value
655739
656740
if (!isEditMode.value && saved.surveyId) {
741+
if (isLearningPathContext.value) {
742+
await router.push(buildLearningPathQuestionsRoute(saved.surveyId))
743+
744+
return
745+
}
746+
657747
await router.push({
658748
name: "SurveyQuestions",
659749
params: {

0 commit comments

Comments
 (0)