Skip to content

Commit

Permalink
Merge pull request rancher#10793 from codyrancher/router-link-tag
Browse files Browse the repository at this point in the history
Updating <router-link> to no longer use the deprecated :tag property
  • Loading branch information
codyrancher authored Apr 18, 2024
2 parents b7b3abd + e205b56 commit e09df1d
Show file tree
Hide file tree
Showing 6 changed files with 451 additions and 342 deletions.
23 changes: 15 additions & 8 deletions shell/components/SideNav.vue
Original file line number Diff line number Diff line change
Expand Up @@ -423,17 +423,24 @@ export default {
<!-- Cluster tools -->
<router-link
v-if="showClusterTools"
tag="div"
class="tools"
v-slot="{ href, navigate }"
custom
:to="{name: 'c-cluster-explorer-tools', params: {cluster: clusterId}}"
>
<a
class="tools-button"
@click="collapseAll()"
<div
class="tools"
@click="navigate"
@keypress.enter="navigate"
>
<i class="icon icon-gear" />
<span>{{ t('nav.clusterTools') }}</span>
</a>
<a
class="tools-button"
:href="href"
@click="collapseAll()"
>
<i class="icon icon-gear" />
<span>{{ t('nav.clusterTools') }}</span>
</a>
</div>
</router-link>
<!-- SideNav footer area (seems to be tied to harvester) -->
<div
Expand Down
94 changes: 0 additions & 94 deletions shell/components/TabbedLinks/index.vue

This file was deleted.

39 changes: 30 additions & 9 deletions shell/components/nav/Header.vue
Original file line number Diff line number Diff line change
Expand Up @@ -690,27 +690,48 @@ export default {
</li>
<router-link
v-if="showPreferencesLink"
tag="li"
v-slot="{ href, navigate }"
custom
:to="{name: 'prefs'}"
class="user-menu-item"
>
<a>{{ t('nav.userMenu.preferences') }}</a>
<li
class="user-menu-item"
@click="navigate"
@keypress.enter="navigate"
>
<a :href="href">{{ t('nav.userMenu.preferences') }}</a>
</li>
</router-link>
<router-link
v-if="showAccountAndApiKeyLink"
tag="li"
v-slot="{ href, navigate }"
custom
:to="{name: 'account'}"
class="user-menu-item"
>
<a>{{ t('nav.userMenu.accountAndKeys', {}, true) }}</a>
<li
class="user-menu-item"
@click="navigate"
@keypress.enter="navigate"
>
<a :href="href">{{ t('nav.userMenu.accountAndKeys', {}, true) }}</a>
</li>
</router-link>
<router-link
v-if="authEnabled"
tag="li"
v-slot="{ href, navigate }"
custom
:to="generateLogoutRoute"
class="user-menu-item"
>
<a @blur="showMenu(false)">{{ t('nav.userMenu.logOut') }}</a>
<li
class="user-menu-item"
@click="navigate"
@keypress.enter="navigate"
>
<a
:href="href"
@blur="showMenu(false)"
>{{ t('nav.userMenu.logOut') }}</a>
</li>
</router-link>
</ul>
</template>
Expand Down
154 changes: 49 additions & 105 deletions shell/components/nav/Type.vue
Original file line number Diff line number Diff line change
Expand Up @@ -28,65 +28,10 @@ export default {
},
data() {
return {
near: false,
over: false,
menuPath: this.type.route ? this.$router.resolve(this.type.route)?.route?.path : undefined,
};
return { near: false };
},
computed: {
isCurrent() {
// This is required to avoid scenarios where fragments break vue routers location matching
// For example, the following fails
// Curruent Path /c/c-m-hzqf4tqt/explorer/members#project-membership
// Menu Path /c/c-m-hzqf4tqt/explorer/members
// vue-router exact-path="true" fixes this (https://v3.router.vuejs.org/api/#exact-path),
// but fails when the the current path is a child (for instance a resource detail page)
// Scenarios to consider
// - Fragement world
// Curruent Path /c/c-m-hzqf4tqt/explorer/members#project-membership
// Menu Path /c/c-m-hzqf4tqt/explorer/members
// - Similar current paths
// /c/c-m-hzqf4tqt/fleet/fleet.cattle.io.bundlenamespacemapping
// /c/c-m-hzqf4tqt/fleet/fleet.cattle.io.bundle
// - Other menu items that appear in current menu item
// /c/c-m-hzqf4tqt/fleet
// /c/c-m-hzqf4tqt/fleet/management.cattle.io.fleetworkspace
// If there's no hash the n-link will determine it's linkActiveClass correctly, so avoid this faff
const invalidHash = !this.$route.hash;
// Lets be super safe
const invalidProps = !this.menuPath || !this.$route.path;
if (invalidHash || invalidProps) {
return false;
}
// We're kind of, but in a fixing way, copying n-link --> vue-router link see vue-router/src/components/link.js & vue-router/src/util/route.js
// We're only going to compare the path and ignore query and fragment
if (this.type.exact) {
return this.$route.path === this.menuPath;
}
const currentPath = this.$route.path.split('/');
const menuPath = this.menuPath.split('/');
if (menuPath.length > currentPath.length) {
return false;
}
for (let i = 0; i < menuPath.length; i++) {
if (menuPath[i] !== currentPath[i]) {
return false;
}
}
return true;
},
showFavorite() {
return ( this.type.mode && this.near && showFavoritesFor.includes(this.type.mode) );
},
Expand Down Expand Up @@ -116,14 +61,6 @@ export default {
this.near = val;
},
setOver(val) {
this.over = val;
},
removeFavorite() {
this.$store.dispatch('type-map/removeFavorite', this.type.name);
},
selectType() {
// Prevent issues if custom NavLink is used #5047
if (this.type?.route) {
Expand All @@ -142,63 +79,70 @@ export default {
<router-link
v-if="type.route"
:key="type.name"
v-slot="{ href, navigate, isActive, isExactActive }"
custom
:to="type.route"
tag="li"
class="child nav-type"
:class="{'root': isRoot, [`depth-${depth}`]: true, 'router-link-active': isCurrent}"
:exact="type.exact"
>
<TabTitle
v-if="$router.resolve(type.route).route.path === $route.path"
:show-child="false"
>
{{ type.labelKey ? t(type.labelKey) : (type.labelDisplay || type.label) }}
</TabTitle>
<a
@click="selectType"
@mouseenter="setNear(true)"
@mouseleave="setNear(false)"
<li
class="child nav-type"
:class="{'root': isRoot, [`depth-${depth}`]: true, 'router-link-active': isActive, 'router-link-exact-active': isExactActive}"
@click="navigate"
@keypress.enter="navigate"
>
<span
v-if="type.labelKey"
class="label"
><t :k="type.labelKey" /></span>
<span
v-else
v-clean-html="type.labelDisplay || type.label"
class="label"
:class="{'no-icon': !type.icon}"
/>
<span
v-if="showFavorite || namespaceIcon || showCount"
class="count"
<TabTitle
v-if="isExactActive"
:show-child="false"
>
<Favorite
v-if="showFavorite"
:resource="type.name"
/>
<i
v-if="namespaceIcon"
class="icon icon-namespace"
:class="{'ns-and-icon': showCount}"
{{ type.labelKey ? t(type.labelKey) : (type.labelDisplay || type.label) }}
</TabTitle>
<a
:href="href"
@click="selectType"
@mouseenter="setNear(true)"
@mouseleave="setNear(false)"
>
<span
v-if="type.labelKey"
class="label"
><t :k="type.labelKey" /></span>
<span
v-else
v-clean-html="type.labelDisplay || type.label"
class="label"
:class="{'no-icon': !type.icon}"
/>
<span
v-if="showCount"
>{{ count }}</span>
</span>
</a>
v-if="showFavorite || namespaceIcon || showCount"
class="count"
>
<Favorite
v-if="showFavorite"
:resource="type.name"
/>
<i
v-if="namespaceIcon"
class="icon icon-namespace"
:class="{'ns-and-icon': showCount}"
data-testid="type-namespaced"
/>
<span
v-if="showCount"
data-testid="type-count"
>{{ count }}</span>
</span>
</a>
</li>
</router-link>
<li
v-else-if="type.link"
class="child nav-type"
data-testid="link-type"
>
<a
:href="type.link"
:target="type.target"
rel="noopener noreferrer nofollow"
@click="selectType"
@mouseenter="setNear(true)"
@mouseleave="setNear(false)"
>
<span class="label">{{ type.label }}&nbsp;<i class="icon icon-external-link" /></span>
</a>
Expand Down
Loading

0 comments on commit e09df1d

Please sign in to comment.