@@ -3,6 +3,7 @@ v-breadcrumbs.nav-breadcrumbs.pl-1.d-flex.flex-nowrap(
33 :items ="breadcrumbs" ,
44 large ,
55 v-if ="!$route.meta.landing"
6+ ref ='scrollContainer'
67)
78 template( v-slot:item ="{ item }" )
89 v-breadcrumbs-item.subtitle-1.font-weight-medium (
@@ -14,10 +15,26 @@ v-breadcrumbs.nav-breadcrumbs.pl-1.d-flex.flex-nowrap(
1415</template >
1516
1617<script lang="ts">
17- import { Component , Vue } from ' vue-property-decorator'
18+ import { Component , Vue , Watch } from ' vue-property-decorator'
19+
20+ // Find a nested object by dot-syntax string
21+ // ex. lookup(obj, 'a.b.c') => obj.a.b.c
22+ function lookup(obj : any , path : string ): any {
23+ return path .split (' .' ).reduce ((prev , curr ) => {
24+ return prev ? prev [curr ] : undefined
25+ }, obj )
26+ }
1827
1928@Component
2029export default class Breadcrumbs extends Vue {
30+
31+ @Watch (' breadcrumbs' )
32+ breadcrumbsChanged(newVal : any , oldVal : any ) {
33+ // Scroll to right of container automatically
34+ const container: any = this .$refs .scrollContainer
35+ container .$el .scrollLeft = container .$el .scrollWidth
36+ }
37+
2138 get breadcrumbs() {
2239
2340 /* This generates breadcrumbs for the toolbar dynamically
@@ -26,70 +43,73 @@ export default class Breadcrumbs extends Vue {
2643 the route metadata can be used to map the parameter name to an item
2744 in the store state. For example, the metadata
2845 meta: {
29- paramMap: {
30- jobId: 'jobs',
46+ paramMap: [{
47+ param: 'jobId',
48+ store: 'jobs',
3149 prop: 'name'
32- }
50+ }]
3351 }
3452 will replace the :jobId param with the 'name' property of the job in state.jobs
3553 that matches the id given.
3654 paramMap can also contain a prop 'propBuilder' that will specify how to build
3755 the text string
3856 */
39-
57+
58+ // ex. ['jobs', '114']
4059 const segments = this .$route .path
4160 .replace (' /' , ' ' )
4261 .split (' /' )
4362
63+ // ex. ['jobs', ':jobId]
4464 const matched = this .$route .matched [this .$route .matched .length - 1 ].path
4565 .replace (' /' , ' ' )
4666 .split (' /' )
4767
4868 return segments .map ((pathSegment , i ) => {
4969 let dynamicName
5070 try {
51- // Get param mapping from route metadata
52- const paramMap = this .$route .meta ?.paramMap
5371 // Extract the param name
72+ // ex. jobId
5473 const param = matched [i ].replace (' :' , ' ' )
55-
56- // Get the path in the state of the object
57- const defaultStatePath = segments [ 0 ]
58- const customStatePath = paramMap [ param ]?. split ( ' . ' ) // Split the param map into an array of the nested state keys
74+
75+ // Get param mapping from route metadata
76+ // ex. { param: 'jobId', store: 'jobs', prop: 'name' }
77+ const paramMap = this . $route . meta ?. paramMap . find (( m : any ) => m . param === param )
5978
6079 // Find the item in the store state
61- let item = this .$store .state
62- if (customStatePath ) {
63- // A custom path in the store was defined, ex. 'messages.conversations'
64- customStatePath .forEach ((key : string ) => {
65- item = item [key ]
66- })
67- }
68- else {
69- // Use the first name in the path
70- item = item [defaultStatePath ]
71- }
72- item = item .byId [pathSegment ]
80+ const item = lookup (this .$store .state , paramMap .store )
81+ .byId [this .$route .params [param ]]
7382
7483 // Use the specified prop or propBuilder to get the name of the object
75- dynamicName = paramMap .propBuilder ? paramMap .propBuilder (item ) : item [paramMap .prop || ' name' ]
84+ dynamicName = paramMap .propBuilder
85+ ? paramMap .propBuilder (item )
86+ : lookup (item , paramMap .prop || ' name' )
7687 }
7788 catch (e ) {
7889 dynamicName = pathSegment
7990 }
8091
81- return {
82- text: matched [i ]?.includes (' :' ) ? dynamicName : pathSegment ,
83- to: ' /' + segments .slice (0 , i + 1 ).join (' /' ),
92+ // Build link text and path
93+ const text = matched [i ]?.includes (' :' ) ? dynamicName : pathSegment
94+ const to = ' /' + segments .slice (0 , i + 1 ).join (' /' )
95+
96+ // Check if the link exists. If not, we only send back the text with no link
97+ const link = this .$router .resolve (to )
98+ const hasActiveRoute = link ?.resolved ?.name !== ' notFound'
99+
100+ if (hasActiveRoute ) {
101+ return { text , to }
84102 }
103+ return { text }
85104 })
86105 }
87106}
88107 </script >
89108
90109<style lang="scss">
91110.nav-breadcrumbs {
92- overflow : hidden ;
111+ overflow-y : hidden ;
112+ overflow-x : auto ;
93113
94114 li {
95115 white-space : nowrap ;
0 commit comments