Skip to content

Commit d3eca51

Browse files
committed
Merge branch 'master' of github.com:chamilo/chamilo-lms
2 parents 9520118 + 0d1abb8 commit d3eca51

26 files changed

+328
-91
lines changed

assets/vue/components/Breadcrumb.vue

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,9 +129,10 @@ function watchResourceNodeLoader() {
129129
const currentRouteName = route.name || ""
130130
const isAssignmentRoute = currentRouteName.startsWith("Assignment")
131131
const isAttendanceRoute = currentRouteName.startsWith("Attendance")
132+
const isDocumentRoute = currentRouteName.startsWith("Documents")
132133
const nodeId = route.params.node || route.query.node
133134
134-
if ((isAssignmentRoute || isAttendanceRoute) && nodeId) {
135+
if ((isAssignmentRoute || isAttendanceRoute || isDocumentRoute) && nodeId) {
135136
try {
136137
store.commit("resourcenode/setResourceNode", null)
137138
const resourceApiId = nodeId.startsWith("/api/") ? nodeId : `/api/resource_nodes/${nodeId}`
@@ -172,6 +173,19 @@ function addDocumentBreadcrumb() {
172173
route: { name: "DocumentsList", params: { node: folder.nodeId }, query: route.query },
173174
})
174175
})
176+
177+
const currentMatched = route.matched.find((r) => r.name === route.name)
178+
const label = currentMatched.meta?.breadcrumb
179+
if (label !== "") {
180+
const finalLabel = label || formatToolName(currentMatched.name)
181+
const alreadyShown = itemList.value.some((item) => item.label === finalLabel)
182+
if (!alreadyShown) {
183+
itemList.value.push({
184+
label: t(finalLabel),
185+
route: { name: currentMatched.name, params: route.params, query: route.query },
186+
})
187+
}
188+
}
175189
}
176190
177191
// Watch route changes to dynamically rebuild the breadcrumb trail

assets/vue/components/attendance/AttendanceForm.vue

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -199,9 +199,9 @@ const submitForm = async () => {
199199
} else {
200200
const created = await attendanceService.createAttendance(postData)
201201
router.push({
202-
name: "AddCalendarEvent",
202+
name: "AttendanceAddCalendarEvent",
203203
params: {
204-
node: parentResourceNodeId.value,
204+
node: getNodeId(created.resourceNode),
205205
id: created.id,
206206
},
207207
query: {
@@ -215,4 +215,10 @@ const submitForm = async () => {
215215
console.error("Error submitting attendance:", error)
216216
}
217217
}
218+
219+
function getNodeId(resourceNode) {
220+
if (!resourceNode || !resourceNode["@id"]) return 0
221+
const parts = resourceNode["@id"].split("/")
222+
return parseInt(parts[parts.length - 1])
223+
}
218224
</script>

assets/vue/components/course/CourseCard.vue

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ import { computed } from "vue"
6363
import { isEmpty } from "lodash"
6464
import { useFormatDate } from "../../composables/formatDate"
6565
import { usePlatformConfig } from "../../store/platformConfig"
66+
import { useI18n } from "vue-i18n"
6667
6768
const { abbreviatedDatetime } = useFormatDate()
6869
@@ -91,6 +92,27 @@ const props = defineProps({
9192
const platformConfigStore = usePlatformConfig()
9293
const showCourseDuration = computed(() => "true" === platformConfigStore.getSetting("course.show_course_duration"))
9394
95+
const { t } = useI18n()
96+
97+
const showRemainingDays = computed(() => {
98+
return platformConfigStore.getSetting("session.session_list_view_remaining_days") === "true"
99+
})
100+
101+
const daysRemainingText = computed(() => {
102+
if (!showRemainingDays.value || !props.session?.displayEndDate) return null
103+
104+
const endDate = new Date(props.session.displayEndDate)
105+
if (isNaN(endDate)) return null
106+
107+
const today = new Date()
108+
const diff = Math.floor((endDate - today) / (1000 * 60 * 60 * 24))
109+
110+
if (diff > 1) return `${diff} days remaining`
111+
if (diff === 1) return t("Ends tomorrow")
112+
if (diff === 0) return t("Ends today")
113+
return t("Expired")
114+
})
115+
94116
const teachers = computed(() => {
95117
if (props.session?.courseCoachesSubscriptions) {
96118
return props.session.courseCoachesSubscriptions
@@ -109,6 +131,10 @@ const teachers = computed(() => {
109131
})
110132
111133
const sessionDisplayDate = computed(() => {
134+
if (daysRemainingText.value) {
135+
return daysRemainingText.value
136+
}
137+
112138
const dateString = []
113139
114140
if (props.session) {

assets/vue/composables/sidebarMenu.js

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,25 @@ export function useSidebarMenu() {
1414
const enrolledStore = useEnrolledStore()
1515
const { items: socialItems } = useSocialMenuItems()
1616
const showTabsSetting = platformConfigStore.getSetting("platform.show_tabs")
17-
const showCatalogue = platformConfigStore.getSetting("platform.catalog_show_courses_sessions")
18-
const allowStudentCatalogue = platformConfigStore.getSetting("display.allow_students_to_browse_courses") !== "false"
17+
const rawShowCatalogue = platformConfigStore.getSetting("platform.catalog_show_courses_sessions")
18+
const showCatalogue = Number(rawShowCatalogue)
19+
const isAnonymous = !securityStore.isAuthenticated
20+
const isPrivilegedUser = securityStore.isAdmin || securityStore.isTeacher || securityStore.isHRM || securityStore.isSessionAdmin
21+
const allowStudentCatalogue = computed(() => {
22+
if (isAnonymous) {
23+
return platformConfigStore.getSetting("course.course_catalog_published") !== "false"
24+
}
25+
26+
if (isPrivilegedUser) {
27+
return true
28+
}
29+
30+
if (securityStore.isStudent) {
31+
return platformConfigStore.getSetting("display.allow_students_to_browse_courses") !== "false"
32+
}
33+
34+
return false
35+
})
1936

2037
const isActive = (item) => {
2138
if (item.route) {
@@ -82,7 +99,7 @@ export function useSidebarMenu() {
8299
const menuItemsAfterMyCourse = computed(() => {
83100
const items = []
84101

85-
if (allowStudentCatalogue && showTabsSetting.indexOf("catalogue") > -1) {
102+
if (allowStudentCatalogue.value && showTabsSetting.indexOf("catalogue") > -1) {
86103
if (showCatalogue === 0 || showCatalogue === 2) {
87104
items.push(createMenuItem("catalogue", "mdi-bookmark-multiple", "Explore more courses", "CatalogueCourses"))
88105
}

assets/vue/router/attendance.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,24 +16,28 @@ export default {
1616
component: () => import("../views/attendance/AttendanceCreate.vue"),
1717
},
1818
{
19-
name: "EditAttendance",
19+
name: "AttendanceEditAttendance",
2020
path: "edit/:id",
2121
component: () => import("../views/attendance/AttendanceEdit.vue"),
22+
meta: { breadcrumb: "Edit attendance" },
2223
},
2324
{
2425
name: "AttendanceSheetList",
2526
path: ":id?/sheet-list",
2627
component: () => import("../views/attendance/AttendanceSheetList.vue"),
28+
meta: { breadcrumb: "Sheet list" },
2729
},
2830
{
2931
name: "AttendanceCalendarList",
3032
path: ":id?/calendar",
3133
component: () => import("../views/attendance/AttendanceCalendarList.vue"),
34+
meta: { breadcrumb: "Calendar" },
3235
},
3336
{
34-
name: "AddCalendarEvent",
37+
name: "AttendanceAddCalendarEvent",
3538
path: ":id?/calendar/create",
3639
component: () => import("../views/attendance/AttendanceCalendarAdd.vue"),
40+
meta: { breadcrumb: "Add calendar" },
3741
},
3842
{
3943
name: "ExportToPdf",

assets/vue/router/documents.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,13 @@ export default {
99
name: "DocumentsList",
1010
path: "",
1111
component: () => import("../views/documents/DocumentsList.vue"),
12+
meta: { breadcrumb: "" },
1213
},
1314
{
1415
name: "DocumentsCreate",
1516
path: "new",
1617
component: () => import("../views/documents/Create.vue"),
18+
meta: { breadcrumb: "Create file" },
1719
},
1820
{
1921
name: "DocumentsCreateFile",

assets/vue/views/attendance/AttendanceCalendarList.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -228,8 +228,8 @@ const redirectToAttendanceSheet = () => {
228228
229229
const redirectToAddCalendarEvent = () => {
230230
router.push({
231-
name: "AddCalendarEvent",
232-
params: { id: route.params.id },
231+
name: "AttendanceAddCalendarEvent",
232+
params: { node: route.params.node, id: route.params.id },
233233
query: { cid: route.query.cid, sid: route.query.sid, gid: route.query.gid },
234234
})
235235
}

assets/vue/views/attendance/AttendanceList.vue

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,8 @@ const redirectToCreateAttendance = () => {
6464
6565
const redirectToEditAttendance = (attendance) => {
6666
router.push({
67-
name: "EditAttendance",
68-
params: { id: attendance.id },
67+
name: "AttendanceEditAttendance",
68+
params: { node: getNodeId(attendance.resourceNode), id: attendance.id },
6969
query: { cid, sid, gid },
7070
})
7171
}
@@ -136,5 +136,11 @@ const fetchAttendances = async ({ page = 1, rows = 10 } = {}) => {
136136
}
137137
}
138138
139+
function getNodeId(resourceNode) {
140+
if (!resourceNode || !resourceNode["@id"]) return 0
141+
const parts = resourceNode["@id"].split("/")
142+
return parseInt(parts[parts.length - 1])
143+
}
144+
139145
onMounted(fetchAttendances)
140146
</script>

assets/vue/views/attendance/AttendanceSheetList.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -567,7 +567,7 @@ const qrImageUrl = ref("")
567567
const redirectToCalendarList = () => {
568568
router.push({
569569
name: "AttendanceCalendarList",
570-
params: { id: route.params.id },
570+
params: { node: route.params.node, id: route.params.id },
571571
query: { sid, cid, gid },
572572
})
573573
}

assets/vue/views/ccalendarevent/CCalendarEventList.vue

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -210,10 +210,10 @@ const sessionState = reactive({
210210
showSessionDialog: false,
211211
})
212212
213-
async function getCalendarEvents({ startStr, endStr }) {
213+
async function getCalendarEvents({ start, end }) {
214214
const params = {
215-
"startDate[after]": startStr,
216-
"endDate[before]": endStr,
215+
"startDate[after]": start.toISOString(),
216+
"endDate[before]": end.toISOString(),
217217
}
218218
219219
if (course.value) {

assets/vue/views/course/CatalogueCourses.vue

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -246,16 +246,30 @@ const applyAdvancedSearch = () => {
246246
visibleCount.value = rowsPerScroll
247247
}
248248
249+
const isAnonymous = !securityStore.isAuthenticated
250+
const isPrivilegedUser =
251+
securityStore.isAdmin || securityStore.isTeacher || securityStore.isHRM || securityStore.isSessionAdmin
252+
249253
const allowCatalogueAccess = computed(() => {
250-
const allowStudents = platformConfigStore.getSetting("display.allow_students_to_browse_courses") !== "false"
251-
const allowPublished = platformConfigStore.getSetting("course.course_catalog_published") !== "false"
252-
return allowStudents && allowPublished
254+
if (isAnonymous) {
255+
return platformConfigStore.getSetting("course.course_catalog_published") !== "false"
256+
}
257+
258+
if (isPrivilegedUser) {
259+
return true
260+
}
261+
262+
if (securityStore.isStudent) {
263+
return platformConfigStore.getSetting("display.allow_students_to_browse_courses") !== "false"
264+
}
265+
266+
return false
253267
})
254268
255269
if (!allowCatalogueAccess.value) {
256270
if (!securityStore.user?.id) {
257271
router.push({ name: "Login" })
258-
} else if (securityStore.user?.status === 5) {
272+
} else if (securityStore.isStudent) {
259273
router.push({ name: "Home" })
260274
} else {
261275
router.push({ name: "Index" })

assets/vue/views/terms/TermsLayout.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<template>
22
<div class="terms-layout">
33
<header>
4-
<h1>{{ t("Terms and conditions") }}</h1>
4+
<h1>{{ t("Terms and Conditions") }}</h1>
55
</header>
66

77
<main>

public/main/exercise/exercise_report.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -478,7 +478,7 @@
478478
$actions .= '<a id="export_opener" href="'.api_get_self().'?export_report=1&exerciseId='.$exercise_id.'" >'.
479479
Display::getMdiIcon('content-save', 'ch-tool-icon', null, ICON_SIZE_MEDIUM, get_lang('Export')).'</a>';
480480
$actions .= Display::url(
481-
Display::getMdiIcon(ActionIcon::REFRESH, 'ch-tool-icon', null, ICON_SIZE_MEDIUM, get_lang('Recalculate Results')),
481+
Display::getMdiIcon(ActionIcon::REFRESH, 'ch-tool-icon', null, ICON_SIZE_MEDIUM, get_lang('Recalculate results')),
482482
api_get_path(WEB_CODE_PATH).'exercise/recalculate_all.php?'.api_get_cidreq()."&exercise=$exercise_id"
483483
);
484484
$actions .= Display::url(
@@ -520,7 +520,7 @@
520520
);
521521
}
522522
$actions .= '<a class="btn btn--plain" href="question_stats.php?'.api_get_cidreq().'&id='.$exercise_id.'">'.
523-
get_lang('QuestionStats').'</a>';
523+
get_lang('Question stats').'</a>';
524524
}
525525
} else {
526526
$actions .= '<a href="exercise.php">'.

public/main/exercise/question_stats.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
api_not_allowed(true);
3131
}
3232

33-
$nameTools = get_lang('ExerciseManagement');
33+
$nameTools = get_lang('Tests management');
3434
$interbreadcrumb[] = [
3535
'url' => 'exercise.php?'.api_get_cidreq(),
3636
'name' => get_lang('Exercises'),
@@ -42,7 +42,7 @@
4242

4343
$interbreadcrumb[] = [
4444
'url' => 'exercise_report.php?'.api_get_cidreq().'&exerciseId='.$exercise->iId,
45-
'name' => get_lang('StudentScore'),
45+
'name' => get_lang('Learner score'),
4646
];
4747
$courseId = api_get_course_int_id();
4848

0 commit comments

Comments
 (0)