-
Notifications
You must be signed in to change notification settings - Fork 27
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Infinite tree #345
Infinite tree #345
Changes from all commits
c91aba3
ac1bfd3
4f1aba0
1ec5ce3
2528441
d8e2bfc
6e7fcd7
21f90ce
6f003fd
15b496e
8fea73a
438df4d
44f03b7
61c3bf9
303e640
a75b89f
d0c83e4
be2487d
edf543e
a9bc2c7
8e7e0f2
2dc994f
2a23013
6d96b22
5fadbc7
0f52a62
09c64d7
c6a7a41
a1f61e9
0a41799
b743743
0dce2a9
c962145
5c1d6f5
7d17009
60d388f
48f6c06
e67d94f
a91b872
8ef7342
5e5b178
c10f00f
9b9c42b
2b5ebcd
13d6c6f
2104535
49d3e6a
787f17f
dcef4ee
7a383d2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -22,7 +22,6 @@ | |
"@lumino/default-theme": "^0.1.8", | ||
"@lumino/widgets": "^1.9.3", | ||
"apollo-boost": "^0.4.4", | ||
"apollo-utilities": "^1.3.2", | ||
"axios-fetch": "^1.1.0", | ||
"cytoscape": "^3.9.0", | ||
"cytoscape-dagre": "^2.2.2", | ||
|
@@ -37,28 +36,30 @@ | |
"graphiql": "^0.17.5", | ||
"graphql": "^14.5.8", | ||
"graphql-tag": "^2.10.1", | ||
"infinite-tree": "git+https://[email protected]/cheton/infinite-tree.git#7bf037ee79b8aa702f5ee605b8ec218bab2533b4", | ||
"jshint": "^2.10.2", | ||
"nprogress": "^0.2.0", | ||
"react": "^15.6.2", | ||
"react-dom": "^15.6.2", | ||
"tippy.js": "^4.3.5", | ||
"vue": "^2.6.10", | ||
"vue-i18n": "^8.14.1", | ||
"vue": "^2.6.11", | ||
"vue-i18n": "^8.15.3", | ||
"vue-markdown": "^2.2.4", | ||
"vue-meta": "^2.3.1", | ||
"vue-router": "^3.1.3", | ||
"vue-spinner": "^1.0.3", | ||
"vue-the-mask": "^0.11.1", | ||
"vue-virtual-scroller": "^1.0.0-rc.2", | ||
"vuetify": "^2.2.6", | ||
"vuex": "^3.1.1", | ||
"vuex": "^3.1.2", | ||
"vuex-router-sync": "^5.0.0" | ||
}, | ||
"devDependencies": { | ||
"@babel/plugin-proposal-class-properties": "^7.8.3", | ||
"@cypress/code-coverage": "^2.0.5", | ||
"@cypress/webpack-preprocessor": "^5.1.2", | ||
"@mdi/font": "^4.5.95", | ||
"@vue/cli-plugin-babel": "^3.12.0", | ||
"@vue/cli-plugin-babel": "^4.1.1", | ||
"@vue/cli-plugin-e2e-cypress": "^4.3.1", | ||
"@vue/cli-plugin-eslint": "^4.2.3", | ||
"@vue/cli-plugin-unit-mocha": "^4.2.3", | ||
|
@@ -74,7 +75,7 @@ | |
"chai": "^4.2.0", | ||
"cross-env": "^6.0.3", | ||
"cross-fetch": "^3.0.4", | ||
"eslint": "^7.0.0", | ||
"eslint": "^6.5.1", | ||
"eslint-config-standard": "^14.1.1", | ||
"eslint-config-vuetify": "^0.5.0", | ||
"eslint-plugin-node": "^11.1.0", | ||
|
@@ -91,13 +92,13 @@ | |
"standard": "^14.3.1", | ||
"subscriptions-transport-ws": "^0.9.16", | ||
"svgo": "^1.3.2", | ||
"vue-cli-plugin-apollo": "^0.21.0", | ||
"vue-cli-plugin-apollo": "^0.21.3", | ||
"vue-cli-plugin-eslint-config-vuetify": "0.0.3", | ||
"vue-cli-plugin-vuetify": "^2.0.5", | ||
"vue-cli-plugin-vuetify-essentials": "^0.8.3", | ||
"vue-template-compiler": "^2.6.10", | ||
"vuetify-loader": "^1.3.0", | ||
"webpack": "^4.41.0" | ||
"vue-template-compiler": "^2.6.11", | ||
"vuetify-loader": "^1.4.3", | ||
"webpack": "^4.41.4" | ||
}, | ||
"resolutions": { | ||
"istanbul-instrumenter-loader/**/istanbul-lib-instrument": "4.0.1" | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,186 @@ | ||
<template> | ||
<!-- NB: we are setting the itemSize to null to use the "Variable size mode" of the vue-virtual-scroller --> | ||
<RecycleScroller | ||
page-mode | ||
ref="scroller" | ||
key-field="id" | ||
:items="tree.nodes" | ||
:item-size="null" | ||
> | ||
<!-- eslint-disable-next-line vue/no-unused-vars --> | ||
<div slot-scope="{ item, index }"> | ||
<slot | ||
name="default" | ||
v-bind="{ | ||
node: item, | ||
tree: tree | ||
}" | ||
/> | ||
</div> | ||
</RecycleScroller> | ||
</template> | ||
|
||
<script> | ||
import { RecycleScroller } from 'vue-virtual-scroller' | ||
// TODO: import InifiniteTree from 'infinite-tree' is not working with dependency installed from git commit. Replace once there is a new release of infinite-tree | ||
import InfiniteTree from '../../../../node_modules/infinite-tree/dist/infinite-tree' | ||
|
||
const lcfirst = (str) => { | ||
str += '' | ||
return str.charAt(0).toLowerCase() + str.substr(1) | ||
} | ||
oliver-sanders marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
export default { | ||
name: 'InfiniteTree', | ||
components: { | ||
RecycleScroller | ||
}, | ||
props: { | ||
treeData: { | ||
type: [Array, Object], | ||
default: () => { | ||
return [] | ||
} | ||
}, | ||
autoOpen: { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thought for later work, for default expansion/collapsing we could use:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Before that would be a bit harder, as the collapse/extend state was controlled in the component. The There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Nodes do know their depth 😉 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. True! But I should have explained better. I think I know one case that doesn't translate directly from the GraphQL results to the Tree view. I don't remember how we are using depth (i.e. don't remember which nodes in our schema have it). But say we have a workflow with depth=0, then the next step would be cycle points with depth=1 in the tree. But in our schema, I think the cycle point has a different depth? We also have special cases, like families. I am not sure if the depth in families is using the correct hierarchy that we need for the tree—which is good I think; our GraphQL schema is independent of component. Another corner case is the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Depth is defined on all nodes except jobs, and based on Family hierarchy.. Cycle points in the tree view are really the |
||
type: Boolean, | ||
default: false | ||
}, | ||
selectable: { | ||
type: Boolean, | ||
default: false | ||
}, | ||
loadNodes: { | ||
type: Function, | ||
default: () => {} | ||
}, | ||
shouldSelectNode: { | ||
type: Function, | ||
default: () => {} | ||
}, | ||
shouldLoadNodes: { | ||
type: Function, | ||
default: () => {} | ||
}, | ||
// Callback invoked before updating the tree. | ||
onContentWillUpdate: { | ||
type: Function, | ||
default: null | ||
}, | ||
// Callback invoked when the tree is updated. | ||
onContentDidUpdate: { | ||
type: Function, | ||
default: null | ||
}, | ||
// Callback invoked when a node is opened. | ||
onOpenNode: { | ||
type: Function, | ||
default: null | ||
}, | ||
// Callback invoked when a node is closed. | ||
onCloseNode: { | ||
type: Function, | ||
default: null | ||
}, | ||
// Callback invoked when a node is selected or deselected. | ||
onSelectNode: { | ||
type: Function, | ||
default: null | ||
}, | ||
// Callback invoked before opening a node. | ||
onWillOpenNode: { | ||
type: Function, | ||
default: null | ||
}, | ||
// Callback invoked before closing a node. | ||
onWillCloseNode: { | ||
type: Function, | ||
default: null | ||
}, | ||
// Callback invoked before selecting or deselecting a node. | ||
onWillSelectNode: { | ||
type: Function, | ||
default: null | ||
}, | ||
onKeyUp: { | ||
type: Function, | ||
default: null | ||
}, | ||
onKeyDown: { | ||
type: Function, | ||
default: null | ||
}, | ||
onMouseLeave: { | ||
type: Function, | ||
default: null | ||
}, | ||
onMouseEnter: { | ||
type: Function, | ||
default: null | ||
} | ||
}, | ||
inheritAttrs: false, | ||
data () { | ||
return { | ||
tree: new InfiniteTree({ | ||
el: this.$refs.tree, | ||
...this.$props | ||
}), | ||
nodes: [], | ||
eventHandlers: { | ||
onContentWillUpdate: null, | ||
onContentDidUpdate: null, | ||
onOpenNode: null, | ||
onCloseNode: null, | ||
onSelectNode: null, | ||
onWillOpenNode: null, | ||
onWillCloseNode: null, | ||
onWillSelectNode: null, | ||
onKeyUp: null, | ||
onKeyDown: null, | ||
onMouseEnter: null, | ||
onMouseLeave: null | ||
} | ||
} | ||
}, | ||
watch: { | ||
treeData: { | ||
handler (newValue) { | ||
this.tree.loadData(newValue) | ||
this.nodes = this.tree.nodes | ||
}, | ||
immediate: true | ||
} | ||
}, | ||
mounted () { | ||
// set up event handlers, if any provided | ||
Object.keys(this.eventHandlers).forEach(key => { | ||
if (!this[key]) { | ||
return | ||
} | ||
const eventName = lcfirst(key.substr(2)) // e.g. onContentWillUpdate -> contentWillUpdate | ||
this.eventHandlers[key] = this[key] | ||
this.tree.on(eventName, this.eventHandlers[key]) | ||
}) | ||
}, | ||
beforeDestroy () { | ||
Object.keys(this.eventHandlers).forEach(key => { | ||
if (!this.eventHandlers[key]) { | ||
return | ||
} | ||
const eventName = lcfirst(key.substr(2)) // e.g. onUpdate -> update | ||
this.tree.removeListener(eventName, this.eventHandlers[key]) | ||
this.eventHandlers[key] = null | ||
}) | ||
|
||
this.tree.destroy() | ||
this.tree = null | ||
}, | ||
methods: { | ||
resetListeners () { | ||
this.$refs.scroller.removeListeners() | ||
this.$refs.scroller.addListeners() | ||
} | ||
} | ||
} | ||
</script> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why are we not using the released version?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good question. I thought I had left a comment somewhere... I clearly remember adding a comment above this line, but I had thought I was writing YAML and of course
yarn install
failed.I had to change the GitHub action linter to allow github.com too, but I only mention the issue in the comment there. Let me chase and see what was the issue.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, here it's.
I've downgraded to the latest 1.16.2 release from NPM.
I recall now spending a long time staring at the screen, not understanding why it wouldn't work. After trying every possible setting, and reading the library code, I decided to check if there were un-released commits.
As there were some, I pointed to the latest commit, and everything worked. I cannot tell which commit fixes it, but the next release should include it. And I haven't found any other issues using this commit, so far.
Should we create a follow-up issue set for 0.3, saying why we have that pinned commit in the
package.json
, and that prior to a release of Cylc UI, we should check if there's a version newer than 1.16.2, and if so, what steps we must take (e.g. update version in package.json, remove github.com entry from linter)?