Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 75 additions & 7 deletions assets/vue/components/Breadcrumb.vue
Original file line number Diff line number Diff line change
Expand Up @@ -28,20 +28,20 @@
</template>

<script setup>
import { computed, ref, watch, watchEffect } from "vue"
import { computed, ref, watch, watchEffect, onMounted } from "vue"
import { useRoute, useRouter } from "vue-router"
import { useI18n } from "vue-i18n"
import Breadcrumb from "primevue/breadcrumb"
import { useCidReqStore } from "../store/cidReq"
import { storeToRefs } from "pinia"
import { useStore } from "vuex"

const legacyItems = ref(window.breadcrumb)
const legacyItems = ref([])

const cidReqStore = useCidReqStore()
const route = useRoute()
const router = useRouter()
const { t } = useI18n()
const { t, te } = useI18n()

const { course, session } = storeToRefs(cidReqStore)
const store = useStore()
Expand All @@ -61,6 +61,13 @@ const specialRouteNames = [

const itemList = ref([])

onMounted(() => {
const wb = (window && window.breadcrumb) || []
if (Array.isArray(wb) && wb.length > 0) {
legacyItems.value = wb
}
})

const formatToolName = (name) => {
if (!name) return ""
return name
Expand Down Expand Up @@ -189,6 +196,35 @@ function addDocumentBreadcrumb() {
}
}

/**
* Resolve translated label for /admin/settings/:namespace
*/
function resolveSettingsSectionLabel(nsRaw) {
const ns = String(nsRaw || "").trim()
// Safer because it's already translated server-side.
try {
const current = document.querySelector(".list-group a.bg-gray-25")
const domText = current?.textContent?.trim()
if (domText) {
return domText
}
} catch (e) {}

// i18n candidates
const candidates = [
`settings_section.${ns}`,
`settings_section.${ns.replace(/-/g, "_")}`,
ns,
ns.replace(/[-_]/g, " "),
]
for (const key of candidates) {
const has = typeof te === "function" && te(key)
if (has) return t(key)
}

return ns.replace(/[-_]/g, " ").replace(/\b\w/g, (c) => c.toUpperCase())
}

// Watch route changes to dynamically rebuild the breadcrumb trail
watchEffect(() => {
if ("/" === route.fullPath) return
Expand Down Expand Up @@ -220,10 +256,10 @@ watchEffect(() => {
const mainUrl = window.location.href
const mainPath = mainUrl.indexOf("main/")
legacyItems.value.forEach((item) => {
let newUrl = item.url.toString()
let newUrl = (item.url || "").toString()
if (newUrl.indexOf("main/") > 0) newUrl = "/" + newUrl.substring(mainPath)
if (newUrl === "/") newUrl = "#"
itemList.value.push({ label: item.name, url: newUrl })
itemList.value.push({ label: item.name, url: newUrl || undefined })
})
legacyItems.value = []
} else if (course.value && route.name !== "CourseHome") {
Expand Down Expand Up @@ -268,7 +304,7 @@ watchEffect(() => {
if (mainToolName === "ccalendarevent") {
const cid = Number(route.query?.cid || 0)
const gid = Number(route.query?.gid || 0)
toolLabel = gid > 0 ? "Group agenda" : (cid > 0 ? "Agenda" : "Personal agenda")
toolLabel = gid > 0 ? "Group agenda" : cid > 0 ? "Agenda" : "Personal agenda"
}
itemList.value.push({
label: t(toolLabel),
Expand Down Expand Up @@ -300,10 +336,24 @@ watchResourceNodeLoader()
function cleanIdParam(id) {
if (!id) return undefined
const match = id.toString().match(/(\d+)$/)
return match ? match[1] : id
return match ? id.toString().match(/(\d+)$/)[1] : id
}

function buildManualBreadcrumbIfNeeded() {
// If server already injected legacy breadcrumbs, use them.
if (Array.isArray(legacyItems.value) && legacyItems.value.length > 0) {
const mainUrl = window.location.href
const mainPath = mainUrl.indexOf("main/")
legacyItems.value.forEach((item) => {
let newUrl = (item.url || "").toString()
if (newUrl.indexOf("main/") > 0) newUrl = "/" + newUrl.substring(mainPath)
if (newUrl === "/") newUrl = "#"
itemList.value.push({ label: item.name, url: newUrl || undefined })
})
legacyItems.value = []
return true
}

const whitelist = ["admin"]
const overrides = {
admin: "AdminIndex",
Expand All @@ -316,6 +366,24 @@ function buildManualBreadcrumbIfNeeded() {
return false
}

// /admin/settings/<namespace>
const isAdminSettings = pathSegments[1] === "settings"
if (isAdminSettings) {
const ns = pathSegments[2] || route.params?.namespace || route.query?.namespace || ""
const adminLabel = t("Admin")
itemList.value.push({
label: adminLabel,
route: { name: overrides.admin, params: route.params, query: route.query },
})
itemList.value.push({
label: t("Settings"),
route: { path: "/admin/settings" },
})
const section = resolveSettingsSectionLabel(ns)
itemList.value.push({ label: section })
return true
}

const fullPath = "/" + pathSegments.join("/")
const hasMatchedRoute = router.getRoutes().some((r) => r.path === fullPath)

Expand Down
17 changes: 17 additions & 0 deletions src/CoreBundle/Resources/views/Admin/Settings/default.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -205,3 +205,20 @@
});
</script>
{% endblock %}
{% block javascripts %}
{% set ns = app.request.get('namespace')|default('') %}
{% set sectionLabel =
(namespace_labels is defined and namespace_labels[ns] is defined)
? namespace_labels[ns]
: (ns == 'cas' ? 'CAS' : (ns == 'lp' ? 'Learning path'|trans : (ns|capitalize)|trans))
%}
<script>
window.breadcrumb = [
{ name: "{{ 'Admin'|trans|e('js') }}", url: "/admin" },
{ name: "{{ 'Settings'|trans|e('js') }}", url: "/admin/settings" },
{ name: "{{ sectionLabel|e('js') }}" }
];
</script>

{{ parent() }}
{% endblock %}
Loading