Skip to content

Commit f88d8b3

Browse files
Merge pull request #6509 from christianbeeznest/rna-22255-2
Course: Improve course catalogue settings and filters - refs BT#22255
2 parents 6eed7c6 + d74994f commit f88d8b3

File tree

4 files changed

+87
-24
lines changed

4 files changed

+87
-24
lines changed

assets/vue/components/course/CatalogueCourseCard.vue

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@
121121

122122
<div class="mt-auto pt-2">
123123
<router-link
124-
v-if="isUserInCourse && (course.visibility === 2 || course.visibility === 3)"
124+
v-if="course.subscribed"
125125
:to="{ name: 'CourseHome', params: { id: course.id } }"
126126
>
127127
<Button
@@ -232,11 +232,6 @@ const allowDescription = computed(
232232
() => platformConfigStore.getSetting("course.show_courses_descriptions_in_catalog") !== "false",
233233
)
234234
235-
const isUserInCourse = computed(() => {
236-
if (!props.currentUserId) return false
237-
return props.course.users?.some((user) => user.user.id === props.currentUserId)
238-
})
239-
240235
const durationInHours = computed(() => {
241236
if (!props.course.duration) return "-"
242237
const duration = props.course.duration / 3600

assets/vue/views/course/CatalogueCourses.vue

Lines changed: 71 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,13 @@
2020
icon="pi pi-sliders-h"
2121
@click="showAdvancedSearch = !showAdvancedSearch"
2222
/>
23+
<Button
24+
v-if="showAdvancedSearch"
25+
:label="$t('Apply advanced filters')"
26+
icon="pi pi-check"
27+
class="p-button-sm p-button-success"
28+
@click="applyAdvancedSearch"
29+
/>
2330
<Dropdown
2431
v-if="allSortOptions.length"
2532
v-model="sortField"
@@ -37,12 +44,6 @@
3744
class="pl-10 w-64"
3845
/>
3946
</div>
40-
<Button
41-
:label="$t('Search')"
42-
icon="pi pi-search"
43-
class="p-button-sm p-button-primary"
44-
@click="applyAdvancedSearch"
45-
/>
4647
</div>
4748
</div>
4849
<div
@@ -51,15 +52,17 @@
5152
>
5253
<div class="grid sm:grid-cols-3 gap-4 mb-4">
5354
<InputText
55+
v-if="courseCatalogueSettings.filters?.by_title"
5456
v-model="advancedFilters.title"
5557
:placeholder="$t('Filter by title')"
5658
/>
5759
<InputText
60+
v-if="courseCatalogueSettings.filters?.by_category"
5861
v-model="advancedFilters.category"
5962
:placeholder="$t('Filter by category')"
6063
/>
6164
<Dropdown
62-
v-if="languages.length > 1"
65+
v-if="courseCatalogueSettings.filters?.by_language && languages.length > 1"
6366
v-model="advancedFilters.language"
6467
:options="languages"
6568
optionLabel="originalName"
@@ -78,9 +81,31 @@
7881
:key="field.variable"
7982
>
8083
<InputText
81-
v-if="field.value_type === 'text'"
84+
v-if="[1, 15, 17].includes(field.value_type)"
85+
v-model="advancedFilters[field.variable]"
86+
:placeholder="formatLabel(field)"
87+
class="w-full"
88+
/>
89+
<Textarea
90+
v-else-if="field.value_type === 2"
91+
v-model="advancedFilters[field.variable]"
92+
:placeholder="formatLabel(field)"
93+
class="w-full"
94+
autoResize
95+
/>
96+
<Calendar
97+
v-else-if="field.value_type === 6"
98+
v-model="advancedFilters[field.variable]"
99+
:placeholder="formatLabel(field)"
100+
class="w-full"
101+
dateFormat="yy-mm-dd"
102+
showIcon
103+
/>
104+
<InputText
105+
v-else
82106
v-model="advancedFilters[field.variable]"
83-
:placeholder="field.display_text"
107+
:placeholder="formatLabel(field)"
108+
class="w-full"
84109
/>
85110
</template>
86111
</div>
@@ -137,6 +162,13 @@ import courseService from "../../services/courseService"
137162
const { t } = useI18n()
138163
const sortField = ref("title")
139164
165+
const formatLabel = (field) => {
166+
if (field.display_text) return field.display_text
167+
return field.variable
168+
.replace(/_/g, " ")
169+
.replace(/\b\w/g, (l) => l.toUpperCase())
170+
}
171+
140172
const standardSortOptions = computed(() => {
141173
return courseCatalogueSettings.value.standard_sort_options ?? {}
142174
})
@@ -182,10 +214,18 @@ const securityStore = useSecurityStore()
182214
183215
const platformConfigStore = usePlatformConfig()
184216
const courseCatalogueSettings = computed(() => {
185-
const raw = platformConfigStore.getSetting("course.course_catalog_settings")
186-
if (raw === false || raw === "false") return {}
217+
let raw = platformConfigStore.getSetting("course.course_catalog_settings")
218+
if (!raw || raw === false || raw === "false") return {}
187219
try {
188-
return typeof raw === "string" ? JSON.parse(raw) : (raw ?? {})
220+
if (typeof raw === "string") {
221+
raw = JSON.parse(raw)
222+
}
223+
224+
if (typeof raw.courses === "object") {
225+
return raw.courses
226+
}
227+
228+
return raw
189229
} catch (e) {
190230
console.error("Invalid catalogue settings format", e)
191231
return {}
@@ -204,9 +244,21 @@ const redirectAfterSubscription = computed(
204244
)
205245
206246
const onUserSubscribed = ({ courseId, newUser }) => {
207-
const course = courses.value.find((c) => c.id === courseId)
208-
if (course) {
209-
course.users.push(newUser)
247+
const index = courses.value.findIndex((c) => c.id === courseId)
248+
if (index !== -1) {
249+
const oldCourse = courses.value[index]
250+
const updatedCourse = {
251+
...oldCourse,
252+
subscribed: true,
253+
users: [...(oldCourse.users || []), newUser],
254+
}
255+
256+
courses.value[index] = updatedCourse
257+
const filteredIndex = filteredCourses.value.findIndex((c) => c.id === courseId)
258+
if (filteredIndex !== -1) {
259+
filteredCourses.value[filteredIndex] = updatedCourse
260+
}
261+
applyAdvancedSearch()
210262
if (redirectAfterSubscription.value === "course_home") {
211263
router.push({ name: "CourseHome", params: { id: courseId } })
212264
}
@@ -325,10 +377,11 @@ const load = async () => {
325377
}
326378
}
327379
328-
onMounted(() => {
380+
onMounted(async () => {
329381
window.addEventListener("scroll", handleScroll)
330-
load().then(() => applyAdvancedSearch())
331-
loadExtraFields()
382+
await loadExtraFields()
383+
await load()
384+
applyAdvancedSearch()
332385
})
333386
334387
const clearFilter = () => {

src/CoreBundle/Entity/Course.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -341,6 +341,9 @@ class Course extends AbstractResource implements ResourceInterface, ResourceWith
341341
#[ORM\Column(name: 'popularity', type: 'integer', nullable: false, options: ['default' => 0])]
342342
protected int $popularity = 0;
343343

344+
#[Groups(['course:read'])]
345+
public bool $subscribed = false;
346+
344347
public function __construct()
345348
{
346349
$this->visibility = self::OPEN_PLATFORM;

src/CoreBundle/State/PublicCatalogueCourseStateProvider.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,14 @@ public function provide(Operation $operation, array $uriVariables = [], array $c
7272
;
7373

7474
if (!$onlyShowMatching && !$onlyShowCoursesWithCategory) {
75+
if ($isAuthenticated) {
76+
foreach ($courses as $course) {
77+
if ($course instanceof Course) {
78+
$course->subscribed = $course->hasSubscriptionByUser($user);
79+
}
80+
}
81+
}
82+
7583
return $courses;
7684
}
7785

@@ -94,6 +102,10 @@ public function provide(Operation $operation, array $uriVariables = [], array $c
94102
}
95103

96104
if ($passesExtraField && $passesCategory) {
105+
if ($isAuthenticated && $course instanceof Course) {
106+
$course->subscribed = $course->hasSubscriptionByUser($user);
107+
}
108+
97109
$filtered[] = $course;
98110
}
99111
}

0 commit comments

Comments
 (0)