Skip to content

Commit

Permalink
feat: run-finder panel treeview
Browse files Browse the repository at this point in the history
  • Loading branch information
billyc committed Jul 20, 2021
1 parent 8804b2a commit d8725db
Show file tree
Hide file tree
Showing 7 changed files with 126 additions and 75 deletions.
73 changes: 53 additions & 20 deletions src/components/RunFinderPanel.vue
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,10 @@ de:
.stuff-in-main-panel
.more-stuff

//- a(href="/sql") SQL Test 1 - Postgres
//- a(href="/sqlite") SQL Test 2 - SQLite
.root-files(v-for="zroot in Object.keys(globalState.runFolders)" :key="zroot")
h3 {{ zroot }}

p(v-for="run in filteredRunFolders(zroot)" :key="`${run.root.url}/${run.path}`")
a(@click="onNavigate(run)") {{ run.path }}
//- router-link(:to="`${run.root.url}${run.path}`") {{ run.path }}
tree-view.things(:initialData="runTree[zroot]")

.bottom-panel
//- h3 Search
Expand Down Expand Up @@ -60,37 +55,72 @@ import { Vue, Component, Prop, Watch } from 'vue-property-decorator'
import Colophon from '@/components/Colophon.vue'
import VizCard from '@/components/VizCard.vue'
import TreeView from '@/components/TreeView.vue'
import globalStore from '@/store'
import { FileSystemConfig } from '@/Globals'
import runFinder from '@/js/RunFinder'
interface Run {
root: FileSystemConfig
// firstFolder: string
interface Folder {
root: string
path: string
name: string
children: Folder[]
}
@Component({
components: { Colophon, VizCard },
components: { Colophon, VizCard, TreeView },
})
class MyComponent extends Vue {
private allRuns: Run[] = []
private runTree: { [root: string]: Folder } = {}
private runLookupByPath: { [path: string]: Folder } = {}
private numberOfScannedFolders = 0
private state = globalStore.state
private rootNodes: { [path: string]: Folder[] } = {}
private mounted() {
runFinder.findRuns()
for (const root of Object.keys(this.$store.state.runFolders)) {
this.generateTreeFromFolders(root)
}
}
private filteredRunFolders(zroot: string) {
const allRuns: any[] = this.globalState.runFolders[zroot]
const filtered = allRuns.filter(f => {
const segments = f.path.split('/')
if (segments.length && segments[segments.length - 1].startsWith('.')) return false
return true
})
return filtered
private async generateTreeFromFolders(root: string) {
const allRuns: { path: string }[] = this.globalState.runFolders[root]
const prefix = this.$store.state.svnProjects.filter((p: any) => p.name === root)[0].slug
const rootNode = { root: prefix, path: '/', name: '', children: [] as Folder[] }
this.runTree[root] = rootNode
for (const run of allRuns) {
// don't analyze root node itself
if (!run.path) continue
// console.log('RUN:', run.path)
const lastSlash = run.path.lastIndexOf('/')
const folderName = run.path.substring(lastSlash + 1)
// skip .dot folders
if (folderName.startsWith('.')) {
// console.log('skipping', folderName)
continue
}
// create node
const folder = { root: prefix, path: run.path, name: folderName, children: [] as Folder[] }
// console.log(run.path)
if (!this.runLookupByPath[root + run.path]) this.runLookupByPath[root + run.path] = folder
// add to parent
const parentPath = run.path.substring(0, lastSlash)
// console.log({ parentPath })
const parent = this.runLookupByPath[root + parentPath] || rootNode
// console.log(run.path, 'has parent', parent)
parent.children.push(folder)
}
return rootNode
}
private onNavigate(target: any) {
Expand Down Expand Up @@ -226,6 +256,9 @@ a {
}
}
.things {
margin-left: -1rem;
}
@media only screen and (max-width: 640px) {
.content {
padding: 2rem 1rem 8rem 1rem;
Expand Down
89 changes: 51 additions & 38 deletions src/components/TreeItem.vue
Original file line number Diff line number Diff line change
@@ -1,70 +1,83 @@
<template>
<li>
<!-- <div :class="{ bold: isFolder }" @click="toggle" @dblclick="makeFolder"> -->
<div :root="item.root.url" :xsubfolder="item.path" @click="toggle">
{{ item.name }}
<!-- <span v-if="isFolder">[{{ isOpen ? '-' : '+' }}]</span> -->
</div>
<ul v-show="isOpen" v-if="isFolder">
<tree-item
class="item"
v-for="(child, index) in item.children"
:key="index"
:item="child"
@make-folder="$emit('make-folder', $event)"
@add-item="$emit('add-item', $event)"
></tree-item>
<!-- <li class="add" @click="$emit('add-item', item)">+</li> -->
</ul>
</li>
<template lang="pug">
li
.leaf-node()
i.toggle.fa(v-if="item.children.length" :class="{'fa-plus': !isOpen, 'fa-minus': isOpen}"
@click="toggle"
style="font-size: 0.7rem; margin: 4px 0 auto -8px;"
)
.leaf-label(:root="item.root" :xsubfolder="item.path" @click="activate") {{ item.name }}

ul.children(v-show="isOpen" v-if="isFolder")
tree-item.item(
v-for="(child, index) in item.children"
:key="index"
:item="child"
@navigate="$emit('navigate', $event)"
)

</template>

<script>
<script lang="ts">
import Vue from 'vue'
export default Vue.component('tree-item', {
props: {
item: Object,
item: {} as any,
},
data: function() {
return {
isOpen: true, // default to all-open
isOpen: true, // default to all-closed
}
},
computed: {
isFolder: function() {
return this.item.children && this.item.children.length
const item = this.item as any
return item.children && item.children.length
},
},
methods: {
toggle: function(target) {
const { root, xsubfolder } = target.target.attributes
console.log({ root: root.value, xsubfolder: xsubfolder.value })
activate: function(element: any) {
const { root, xsubfolder } = element.target.attributes
this.$emit('navigate', {
component: 'FolderBrowser',
props: { root, xsubfolder },
props: { root: root.value, xsubfolder: xsubfolder.value },
})
},
// if (this.isFolder) {
// this.isOpen = !this.isOpen
// }
// },
makeFolder: function() {
if (!this.isFolder) {
this.$emit('make-folder', this.item)
this.isOpen = true
}
toggle: function(element: any) {
this.isOpen = !this.isOpen
},
},
})
</script>
<style scoped>

<style scoped lang="scss">
@import '@/styles.scss';
ul {
list-style: none outside none;
}
li {
margin-left: 0.6rem;
line-height: 1.15rem;
}
.item {
margin-right: auto;
cursor: pointer;
}
.leaf-node {
display: flex;
flex-direction: row;
margin-right: auto;
}
.leaf-label:hover {
background-color: var(--bgHover);
}
.leaf-label {
margin-left: 0.15rem;
}
</style>
26 changes: 17 additions & 9 deletions src/components/TreeView.vue
Original file line number Diff line number Diff line change
@@ -1,12 +1,7 @@
<template>
<ul id="demo">
<tree-item
class="item"
:item="treeData"
@make-folder="makeFolder"
@add-item="addItem"
></tree-item>
</ul>
<template lang="pug">
ul
tree-item.item(:item="treeData" :root="true" @navigate="onNavigate")

</template>

<script lang="ts">
Expand All @@ -26,6 +21,14 @@ export default Vue.component('tree-view', {
}
},
methods: {
onNavigate: function(event: any) {
const newPath = `/${event.props.root}/${event.props.xsubfolder}`
try {
this.$router.push(newPath)
} catch (e) {
// duplicate nav is ignored
}
},
makeFolder: function(item: any) {
Vue.set(item, 'children', [])
this.addItem(item)
Expand All @@ -38,3 +41,8 @@ export default Vue.component('tree-view', {
},
})
</script>
<style scoped>
ul {
margin-left: 0.3rem;
}
</style>
1 change: 0 additions & 1 deletion src/fileSystemConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ const fileSystems: FileSystemConfig[] = [
baseURL: 'http://localhost:8000',
needPassword: false,
thumbnail: '/images/thumb-localfiles.jpg',
dashboardFolder: '.dashboards',
},
{
name: 'Public-SVN',
Expand Down
3 changes: 2 additions & 1 deletion src/js/HTTPFileSystem.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,9 +132,10 @@ class SVNFileSystem {
if (!entry) continue

// got one!
const name = entry[1] // regex returns first match in [1]
let name = entry[1] // regex returns first match in [1]

if (name === '../') continue
if (name.startsWith('./')) name = name.substring(2)

if (name.endsWith('/')) dirs.push(name.substring(0, name.length - 1))
else files.push(name)
Expand Down
5 changes: 1 addition & 4 deletions src/js/RunFinder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,7 @@ const fetchFolders = async function(

foundFolders.number++

// if (files.filter(f => f.endsWith('xml.gz')).length) {
if (files.length) {
foundFolders.folders[root.name].push({ root, path: folder })
}
foundFolders.folders[root.name].push({ root, path: folder })
foundFolders.folders[root.name].sort((a: any, b: any) => (a.path < b.path ? -1 : 1))

// save the results
Expand Down
4 changes: 2 additions & 2 deletions src/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ interface GlobalState {
locale: string
needLoginForUrl: string
resizeEvents: number
runFolders: { [root: string]: { folder: string }[] }
runFolders: { [root: string]: { path: string }[] }
runFolderCount: number
statusErrors: string[]
statusMessage: string
Expand Down Expand Up @@ -79,7 +79,7 @@ export default new Vuex.Store({
mutations: {
updateRunFolders(
state: GlobalState,
value: { number: number; folders: { [root: string]: { folder: string }[] } }
value: { number: number; folders: { [root: string]: { path: string }[] } }
) {
state.runFolderCount = value.number
state.runFolders = value.folders
Expand Down

0 comments on commit d8725db

Please sign in to comment.