Node breadcrumbs
Breadcrumbs are served as JSON at `/nodes/{node ID}/breadcrumbs`, with the top-level parent listed first and the node itself listed last: {breadcrumbs: [ ... {_id: "parentID", name: "The Parent Node", node_type: "group", url: "/p/project/parentID"}, {_id: "deadbeefbeefbeefbeeffeee", name: "The Node Itself", node_type: "asset", url: "/p/project/nodeID", _self: true}, ]} When a parent node is missing, it has a breadcrumb like this: {_id: "deadbeefbeefbeefbeeffeee", _exists': false, name': '-unknown-'} Of course this will be the first in the breadcrumbs list, as we won't be able to determine the parent of a deleted/non-existing node. Breadcrumbs are rendered with Vue.js in Blender Cloud (not in Pillar); see projects/view.pug.
This commit is contained in:
@@ -25,6 +25,10 @@ class EventName {
|
||||
static deleted(nodeId) {
|
||||
return `pillar:node:${nodeId}:deleted`;
|
||||
}
|
||||
|
||||
static loaded() {
|
||||
return `pillar:node:loaded`;
|
||||
}
|
||||
}
|
||||
|
||||
function trigger(eventName, data) {
|
||||
@@ -139,6 +143,23 @@ class Nodes {
|
||||
EventName.deleted(nodeId),
|
||||
cb);
|
||||
}
|
||||
|
||||
static triggerLoaded(nodeId) {
|
||||
trigger(EventName.loaded(), {nodeId: nodeId});
|
||||
}
|
||||
|
||||
/**
|
||||
* Listen to events of nodes being loaded for display
|
||||
* @param {Function(Event)} cb
|
||||
*/
|
||||
static onLoaded(cb) {
|
||||
on(EventName.loaded(), cb);
|
||||
}
|
||||
|
||||
static offLoaded(cb) {
|
||||
off(EventName.loaded(), cb);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export { Nodes }
|
||||
|
@@ -0,0 +1,49 @@
|
||||
const TEMPLATE = `
|
||||
<div class='breadcrumbs' v-if="breadcrumbs.length">
|
||||
<ul>
|
||||
<li v-for="crumb in breadcrumbs">
|
||||
<a :href="crumb.url" v-if="!crumb._self">{{ crumb.name }}</a>
|
||||
<template v-else>{{ crumb.name }}</template>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
`
|
||||
|
||||
Vue.component("node-breadcrumbs", {
|
||||
template: TEMPLATE,
|
||||
created() {
|
||||
this.loadBreadcrumbs();
|
||||
pillar.events.Nodes.onLoaded(event => {
|
||||
this.nodeId = event.detail.nodeId;
|
||||
});
|
||||
},
|
||||
props: {
|
||||
nodeId: String,
|
||||
},
|
||||
data() { return {
|
||||
breadcrumbs: [],
|
||||
}},
|
||||
watch: {
|
||||
nodeId() {
|
||||
this.loadBreadcrumbs();
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
loadBreadcrumbs() {
|
||||
// The node ID may not exist (when at project level, for example).
|
||||
if (!this.nodeId) {
|
||||
this.breadcrumbs = [];
|
||||
return;
|
||||
}
|
||||
|
||||
$.get(`/nodes/${this.nodeId}/breadcrumbs`)
|
||||
.done(data => {
|
||||
this.breadcrumbs = data.breadcrumbs;
|
||||
})
|
||||
.fail(error => {
|
||||
toastr.error(xhrErrorResponseMessage(error), "Unable to load breadcrumbs");
|
||||
})
|
||||
;
|
||||
},
|
||||
},
|
||||
});
|
@@ -1,3 +1,4 @@
|
||||
import './breadcrumbs/Breadcrumbs'
|
||||
import './comments/CommentTree'
|
||||
import './customdirectives/click-outside'
|
||||
import { UnitOfWorkTracker } from './mixins/UnitOfWorkTracker'
|
||||
|
Reference in New Issue
Block a user