diff --git a/src/Globals.ts b/src/Globals.ts
index 167cb43f..7196633a 100644
--- a/src/Globals.ts
+++ b/src/Globals.ts
@@ -15,6 +15,12 @@ export enum Status {
WARNING,
}
+export type YamlConfigs = {
+ dashboards: { [filename: string]: string }
+ topsheets: { [filename: string]: string }
+ vizes: { [filename: string]: string }
+}
+
export const UI_FONT =
"'Titillium Web', 'Roboto', 'Open Sans', Avenir, Arial, Helvetica, sans-serif"
diff --git a/src/components/TopSheet/TopSheet.vue b/src/components/TopSheet/TopSheet.vue
index f9299835..a3083997 100644
--- a/src/components/TopSheet/TopSheet.vue
+++ b/src/components/TopSheet/TopSheet.vue
@@ -15,7 +15,7 @@
diff --git a/src/js/HTTPFileSystem.ts b/src/js/HTTPFileSystem.ts
index 534adf78..f643ff56 100644
--- a/src/js/HTTPFileSystem.ts
+++ b/src/js/HTTPFileSystem.ts
@@ -1,6 +1,14 @@
-import { DirectoryEntry, FileSystemConfig } from '@/Globals'
+import micromatch from 'micromatch'
+import { DirectoryEntry, FileSystemConfig, YamlConfigs } from '@/Globals'
import globalStore from '@/store'
+const YAML_FOLDER = 'simwrapper'
+
+// Cache directory listings for each slug & directory
+const CACHE: { [slug: string]: { [dir: string]: DirectoryEntry } } = {}
+
+// ---------------------------------------------------------------------------
+
class SVNFileSystem {
private baseUrl: string
private urlId: string
@@ -12,6 +20,12 @@ class SVNFileSystem {
this.baseUrl = project.baseURL
if (!project.baseURL.endsWith('/')) this.baseUrl += '/'
+
+ if (!CACHE[this.urlId]) CACHE[this.urlId] = {}
+ }
+
+ public clearCache() {
+ CACHE[this.urlId] = {}
}
public cleanURL(scaryPath: string) {
@@ -38,7 +52,7 @@ class SVNFileSystem {
}
const myRequest = new Request(path, { headers })
- const response = await fetch(myRequest).then(response => {
+ const response = await fetch(myRequest).then((response) => {
// Check HTTP Response code: 200 is OK, everything else is a problem
if (response.status != 200) {
console.log('Status:', response.status)
@@ -82,10 +96,78 @@ class SVNFileSystem {
// don't download any files!
if (!stillScaryPath.endsWith('/')) stillScaryPath += '/'
+ // Use cached version if we have it
+ const cachedEntry = CACHE[this.urlId][stillScaryPath]
+ if (cachedEntry) return cachedEntry
+
+ // Generate and cache the listing
const response = await this._getFileResponse(stillScaryPath).then()
const htmlListing = await response.text()
+ const dirEntry = this.buildListFromHtml(htmlListing)
+ CACHE[this.urlId][stillScaryPath] = dirEntry
+
+ return dirEntry
+ }
+
+ async findAllYamlConfigs(folder: string): Promise {
+ const yamls: YamlConfigs = { dashboards: {}, topsheets: {}, vizes: {} }
+
+ const configFolders = []
+
+ // first find all simwrapper folders
+ let currentPath = '/'
+ const { dirs } = await this.getDirectory(currentPath)
+ if (dirs.indexOf(YAML_FOLDER) > -1)
+ configFolders.push(`${currentPath}/${YAML_FOLDER}`.replaceAll('//', '/'))
+
+ const pathChunks = folder.split('/')
+ for (const chunk of pathChunks) {
+ currentPath = `${currentPath}${chunk}/`
+ const { dirs } = await this.getDirectory(currentPath)
+ if (dirs.indexOf(YAML_FOLDER) > -1)
+ configFolders.push(`${currentPath}/${YAML_FOLDER}`.replaceAll('//', '/'))
+ }
+
+ // also add current working folder as final option, which supercedes all others
+ configFolders.push(folder)
+
+ // console.log('configFolders', configFolders)
+
+ // find all dashboards, topsheets, and viz-* yamls in each configuration folder.
+ // Overwrite keys as we go; identically-named configs from parent folders get superceded as we go.
+ const dashboard = 'dashboard*.y?(a)ml'
+ const topsheet = 'topsheet*.y?(a)ml'
+ const viz = 'viz*.y?(a)ml'
+
+ for (const configFolder of configFolders) {
+ const { files } = await this.getDirectory(configFolder)
+
+ micromatch
+ .match(files, dashboard)
+ .map((yaml) => (yamls.dashboards[yaml] = `${configFolder}/${yaml}`.replaceAll('//', '/')))
+
+ micromatch
+ .match(files, topsheet)
+ .map((yaml) => (yamls.topsheets[yaml] = `${configFolder}/${yaml}`.replaceAll('//', '/')))
+
+ micromatch
+ .match(files, viz)
+ .map((yaml) => (yamls.vizes[yaml] = `${configFolder}/${yaml}`.replaceAll('//', '/')))
+ }
- return this.buildListFromHtml(htmlListing)
+ // Sort them all by filename
+ yamls.dashboards = Object.fromEntries(
+ Object.entries(yamls.dashboards).sort((a, b) => (a[0] > b[0] ? 1 : -1))
+ )
+ yamls.topsheets = Object.fromEntries(
+ Object.entries(yamls.topsheets).sort((a, b) => (a[0] > b[0] ? 1 : -1))
+ )
+ yamls.vizes = Object.fromEntries(
+ Object.entries(yamls.vizes).sort((a, b) => (a[0] > b[0] ? 1 : -1))
+ )
+
+ console.log(yamls)
+ return yamls
}
private buildListFromHtml(data: string): DirectoryEntry {
diff --git a/src/js/RunFinder.ts b/src/js/RunFinder.ts
index 0590bd88..478adc92 100644
--- a/src/js/RunFinder.ts
+++ b/src/js/RunFinder.ts
@@ -5,7 +5,7 @@ import { FileSystemConfig } from '@/Globals'
let foundFolders = { number: 0, folders: {} as any }
-const findRuns = function() {
+const findRuns = function () {
// check date and time
const storedUpdate = localStorage.getItem('RunFinder.lastUpdate')
const lastUpdate = storedUpdate ? parseInt(storedUpdate) : 0
@@ -38,37 +38,34 @@ const populate = () => {
foundFolders = { number: 0, folders: {} }
store.commit('updateRunFolders', foundFolders)
- store.state.svnProjects.forEach(root => {
+ store.state.svnProjects.forEach((root) => {
if (!root.hidden && root.slug !== 'gallery') drillIntoRootProject(root)
})
}
-const drillIntoRootProject = function(root: FileSystemConfig) {
+const drillIntoRootProject = function (root: FileSystemConfig) {
console.log('Drilling into:', root.name)
+
const fileSystem = new HTTPFileSystem(root)
+ fileSystem.clearCache()
foundFolders.folders[root.name] = []
fetchFolders(root, fileSystem, '')
}
-const fetchFolders = async function(
+const fetchFolders = async function (
root: FileSystemConfig,
fileSystem: HTTPFileSystem,
folder: string
) {
try {
// skip some big folders we know we don't care about
- if (root.skipList && root.skipList.filter(f => folder.endsWith(f)).length) return
+ if (root.skipList && root.skipList.filter((f) => folder.endsWith(f)).length) return
// skip .dot and __MACOSX folders
if (folder.endsWith('__MACOSX')) return
- if (
- folder
- .split('/')
- .pop()
- ?.startsWith('.')
- ) {
+ if (folder.split('/').pop()?.startsWith('.')) {
return
}
diff --git a/src/plugins/agent-animation/AgentAnimation.vue b/src/plugins/agent-animation/AgentAnimation.vue
index 36f548af..a7c7fb7a 100644
--- a/src/plugins/agent-animation/AgentAnimation.vue
+++ b/src/plugins/agent-animation/AgentAnimation.vue
@@ -212,9 +212,13 @@ class MyComponent extends Vue {
private async getVizDetails() {
// first get config
try {
- const text = await this.myState.fileApi.getFileText(
- this.myState.subfolder + '/' + this.myState.yamlConfig
- )
+ // might be a project config:
+ const filename =
+ this.myState.yamlConfig.indexOf('/') > -1
+ ? this.myState.yamlConfig
+ : this.myState.subfolder + '/' + this.myState.yamlConfig
+
+ const text = await this.myState.fileApi.getFileText(filename)
this.vizDetails = yaml.parse(text)
} catch (e) {
console.log('failed')
@@ -367,7 +371,7 @@ globalStore.commit('registerPlugin', {
kebabName: 'agent-animation',
prettyName: 'Agent Animation',
description: 'birds',
- filePatterns: ['viz-agent-anim*.y?(a)ml'],
+ filePatterns: ['**/viz-agent-anim*.y?(a)ml'],
component: MyComponent,
} as VisualizationPlugin)
diff --git a/src/plugins/aggregate-od/AggregateOd.vue b/src/plugins/aggregate-od/AggregateOd.vue
index d0f2fe56..e70fce25 100644
--- a/src/plugins/aggregate-od/AggregateOd.vue
+++ b/src/plugins/aggregate-od/AggregateOd.vue
@@ -334,9 +334,13 @@ class MyComponent extends Vue {
if (!this.myState.fileApi) return
// first get config
try {
- const text = await this.myState.fileApi.getFileText(
- this.myState.subfolder + '/' + this.myState.yamlConfig
- )
+ // might be a project config:
+ const filename =
+ this.myState.yamlConfig.indexOf('/') > -1
+ ? this.myState.yamlConfig
+ : this.myState.subfolder + '/' + this.myState.yamlConfig
+
+ const text = await this.myState.fileApi.getFileText(filename)
this.vizDetails = yaml.parse(text)
} catch (err) {
const e = err as any
@@ -1242,7 +1246,7 @@ globalStore.commit('registerPlugin', {
kebabName: 'aggregate-od',
prettyName: 'Origin/Destination Patterns',
description: 'Depicts aggregate O/D flows between areas.',
- filePatterns: ['viz-od*.y?(a)ml'],
+ filePatterns: ['**/viz-od*.y?(a)ml'],
component: MyComponent,
} as VisualizationPlugin)
diff --git a/src/plugins/carrier-viewer/Plugin.vue b/src/plugins/carrier-viewer/Plugin.vue
index d6e95ea1..1b94539e 100644
--- a/src/plugins/carrier-viewer/Plugin.vue
+++ b/src/plugins/carrier-viewer/Plugin.vue
@@ -515,9 +515,13 @@ class CarrierPlugin extends Vue {
if (!this.myState.fileApi) return
// first get config
try {
- const text = await this.myState.fileApi.getFileText(
- this.myState.subfolder + '/' + this.myState.yamlConfig
- )
+ // might be a project config:
+ const filename =
+ this.myState.yamlConfig.indexOf('/') > -1
+ ? this.myState.yamlConfig
+ : this.myState.subfolder + '/' + this.myState.yamlConfig
+
+ const text = await this.myState.fileApi.getFileText(filename)
this.vizDetails = YAML.parse(text)
if (!this.vizDetails.center) this.vizDetails.center = [13.4, 52.5]
} catch (e) {
@@ -771,7 +775,7 @@ globalStore.commit('registerPlugin', {
kebabName: 'carrier-viewer',
prettyName: 'Carrier Viewer',
description: 'For freight etc!',
- filePatterns: ['viz-carrier*.y?(a)ml'],
+ filePatterns: ['**/viz-carrier*.y?(a)ml'],
component: CarrierPlugin,
} as VisualizationPlugin)
diff --git a/src/plugins/link-vols/LinkVolumes.vue b/src/plugins/link-vols/LinkVolumes.vue
index a73ca9f3..b5a029f1 100644
--- a/src/plugins/link-vols/LinkVolumes.vue
+++ b/src/plugins/link-vols/LinkVolumes.vue
@@ -327,11 +327,16 @@ class MyComponent extends Vue {
private async getVizDetails() {
try {
- const text = await this.myState.fileApi.getFileText(
- this.myState.subfolder + '/' + this.myState.yamlConfig
- )
+ // might be a project config:
+ const filename =
+ this.myState.yamlConfig.indexOf('/') > -1
+ ? this.myState.yamlConfig
+ : this.myState.subfolder + '/' + this.myState.yamlConfig
+
+ const text = await this.myState.fileApi.getFileText(filename)
this.vizDetails = yaml.parse(text)
- } catch (e) {
+ } catch (err) {
+ const e = err as any
// maybe it failed because password?
if (this.myState.fileSystem && this.myState.fileSystem.needPassword && e.status === 401) {
globalStore.commit('requestLogin', this.myState.fileSystem.slug)
@@ -966,7 +971,7 @@ globalStore.commit('registerPlugin', {
kebabName: 'link-volumes',
prettyName: 'Volumes',
description: 'Aggregate volumes on network links',
- filePatterns: ['viz-link*.y?(a)ml'],
+ filePatterns: ['**/viz-link*.y?(a)ml'],
component: MyComponent,
} as VisualizationPlugin)
diff --git a/src/plugins/links-gl/LinkVolumes.vue b/src/plugins/links-gl/LinkVolumes.vue
index 1c3a491e..5d19f8d3 100644
--- a/src/plugins/links-gl/LinkVolumes.vue
+++ b/src/plugins/links-gl/LinkVolumes.vue
@@ -240,9 +240,13 @@ class MyPlugin extends Vue {
// first get config
try {
- const text = await this.myState.fileApi.getFileText(
- this.myState.subfolder + '/' + this.myState.yamlConfig
- )
+ // might be a project config:
+ const filename =
+ this.myState.yamlConfig.indexOf('/') > -1
+ ? this.myState.yamlConfig
+ : this.myState.subfolder + '/' + this.myState.yamlConfig
+
+ const text = await this.myState.fileApi.getFileText(filename)
this.vizDetails = YAML.parse(text)
} catch (err) {
console.error('failed')
@@ -593,7 +597,7 @@ globalStore.commit('registerPlugin', {
kebabName: 'links-gl',
prettyName: 'Links',
description: 'Network link attributes',
- filePatterns: ['viz-gl-link*.y?(a)ml'],
+ filePatterns: ['**/viz-link*.y?(a)ml'],
component: MyPlugin,
} as VisualizationPlugin)
diff --git a/src/plugins/sankey/SankeyDiagram.vue b/src/plugins/sankey/SankeyDiagram.vue
index 966e21ca..31ebc29c 100644
--- a/src/plugins/sankey/SankeyDiagram.vue
+++ b/src/plugins/sankey/SankeyDiagram.vue
@@ -114,7 +114,11 @@ class MyComponent extends Vue {
try {
this.loadingText = 'Loading files...'
- const text = await this.fileApi.getFileText(this.subfolder + '/' + this.yamlConfig)
+ // might be a project config:
+ const filename =
+ this.yamlConfig.indexOf('/') > -1 ? this.yamlConfig : this.subfolder + '/' + this.yamlConfig
+
+ const text = await this.fileApi.getFileText(filename)
this.vizDetails = yaml.parse(text)
this.$emit('title', this.vizDetails.title)
@@ -221,7 +225,7 @@ globalStore.commit('registerPlugin', {
kebabName: 'sankey-diagram',
prettyName: 'Flow Diagram',
description: 'Depicts flows between choices',
- filePatterns: ['sankey*.y?(a)ml'],
+ filePatterns: ['**/sankey*.y?(a)ml', '**/viz-sankey*.y?(a)ml'],
component: MyComponent,
} as VisualizationPlugin)
diff --git a/src/plugins/shape-file/ShapeFile.vue b/src/plugins/shape-file/ShapeFile.vue
index 306b71b5..b642336d 100644
--- a/src/plugins/shape-file/ShapeFile.vue
+++ b/src/plugins/shape-file/ShapeFile.vue
@@ -289,11 +289,6 @@ class MyPlugin extends Vue {
this.$store.commit('setFullScreen', false)
}
- // private handleClickColumnSelector() {
- // console.log('click!')
- // this.isButtonActiveColumn = !this.isButtonActiveColumn
- // }
-
private async loadShapefile() {
if (!this.myState.fileApi) return
diff --git a/src/plugins/transit-demand/TransitDemand.vue b/src/plugins/transit-demand/TransitDemand.vue
index de82b2ec..cc5f1b07 100644
--- a/src/plugins/transit-demand/TransitDemand.vue
+++ b/src/plugins/transit-demand/TransitDemand.vue
@@ -385,9 +385,13 @@ class MyComponent extends Vue {
private async loadYamlConfig() {
// first get config
try {
- const text = await this.myState.fileApi.getFileText(
- this.myState.subfolder + '/' + this.myState.yamlConfig
- )
+ // might be a project config:
+ const filename =
+ this.myState.yamlConfig.indexOf('/') > -1
+ ? this.myState.yamlConfig
+ : this.myState.subfolder + '/' + this.myState.yamlConfig
+
+ const text = await this.myState.fileApi.getFileText(filename)
this.vizDetails = yaml.parse(text)
} catch (e) {
// maybe it failed because password?
diff --git a/src/plugins/vega-lite/VegaLite.vue b/src/plugins/vega-lite/VegaLite.vue
index 00345e0a..132ff005 100644
--- a/src/plugins/vega-lite/VegaLite.vue
+++ b/src/plugins/vega-lite/VegaLite.vue
@@ -154,9 +154,13 @@ class VegaComponent extends Vue {
try {
this.loadingText = 'Loading chart...'
- json = await this.myState.fileApi.getFileJson(
- this.myState.subfolder + '/' + this.myState.yamlConfig
- )
+ // might be a project config:
+ const filename =
+ this.myState.yamlConfig.indexOf('/') > -1
+ ? this.myState.yamlConfig
+ : this.myState.subfolder + '/' + this.myState.yamlConfig
+
+ json = await this.myState.fileApi.getFileJson(filename)
this.description = json.description ? json.description : ''
this.title = json.title
@@ -226,7 +230,7 @@ globalStore.commit('registerPlugin', {
kebabName: 'vega-lite',
prettyName: 'Chart',
description: 'Interactive chart visualization',
- filePatterns: ['*.vega.json'],
+ filePatterns: ['**/*.vega.json'],
component: VegaComponent,
} as VisualizationPlugin)
diff --git a/src/plugins/vehicle-animation/VehicleAnimation.vue b/src/plugins/vehicle-animation/VehicleAnimation.vue
index cff3e786..da34d1a8 100644
--- a/src/plugins/vehicle-animation/VehicleAnimation.vue
+++ b/src/plugins/vehicle-animation/VehicleAnimation.vue
@@ -276,9 +276,13 @@ class VehicleAnimation extends Vue {
// first get config
try {
- const text = await this.myState.fileApi.getFileText(
- this.myState.subfolder + '/' + this.myState.yamlConfig
- )
+ // might be a project config:
+ const filename =
+ this.myState.yamlConfig.indexOf('/') > -1
+ ? this.myState.yamlConfig
+ : this.myState.subfolder + '/' + this.myState.yamlConfig
+
+ const text = await this.myState.fileApi.getFileText(filename)
this.vizDetails = YAML.parse(text)
if (!this.vizDetails.center) this.vizDetails.center = [14, 52.1]
} catch (err) {
@@ -709,7 +713,7 @@ globalStore.commit('registerPlugin', {
kebabName: 'vehicle-animation',
prettyName: 'Trip Viewer',
description: 'Deck.gl based trip viewer',
- filePatterns: ['viz-vehicles*.y?(a)ml'],
+ filePatterns: ['**/viz-vehicles*.y?(a)ml'],
component: VehicleAnimation,
} as VisualizationPlugin)
diff --git a/src/plugins/xy-hexagons/XyHexagons.vue b/src/plugins/xy-hexagons/XyHexagons.vue
index 687eb3a8..51c6490b 100644
--- a/src/plugins/xy-hexagons/XyHexagons.vue
+++ b/src/plugins/xy-hexagons/XyHexagons.vue
@@ -375,39 +375,49 @@ class XyHexagons extends Vue {
}
private async getVizDetails() {
- if (!this.myState.fileApi) return
-
const hasYaml = new RegExp('.*(yml|yaml)$').test(this.myState.yamlConfig)
- if (!hasYaml) {
- let projection = 'EPSG:31468' // 'EPSG:25832', // 'EPSG:31468', // TODO: fix
- if (!this.myState.thumbnail) {
- projection = prompt('Enter projection: e.g. "EPSG:31468"') || 'EPSG:31468'
- if (!!parseInt(projection, 10)) projection = 'EPSG:' + projection
- }
- // output_trips:
- this.vizDetails = {
- title: 'Output Trips',
- description: this.myState.yamlConfig,
- file: this.myState.yamlConfig,
- projection,
- aggregations: {
- 'Trip Summary': [
- { title: 'Origins', x: 'start_x', y: 'start_y' },
- { title: 'Destinations', x: 'end_x', y: 'end_y' },
- ],
- },
- }
- this.$emit('title', this.vizDetails.title)
- // this.solveProjection()
- return
+ if (hasYaml) {
+ await this.loadYamlConfig()
+ } else {
+ this.loadOutputTripsConfig()
}
+ }
- // first get config
+ private loadOutputTripsConfig() {
+ let projection = 'EPSG:31468' // 'EPSG:25832', // 'EPSG:31468', // TODO: fix
+ if (!this.myState.thumbnail) {
+ projection = prompt('Enter projection: e.g. "EPSG:31468"') || 'EPSG:31468'
+ if (!!parseInt(projection, 10)) projection = 'EPSG:' + projection
+ }
+ // output_trips:
+ this.vizDetails = {
+ title: 'Output Trips',
+ description: this.myState.yamlConfig,
+ file: this.myState.yamlConfig,
+ projection,
+ aggregations: {
+ 'Trip Summary': [
+ { title: 'Origins', x: 'start_x', y: 'start_y' },
+ { title: 'Destinations', x: 'end_x', y: 'end_y' },
+ ],
+ },
+ }
+ this.$emit('title', this.vizDetails.title)
+ // this.solveProjection()
+ return
+ }
+
+ private async loadYamlConfig() {
+ if (!this.myState.fileApi) return
try {
- const text = await this.myState.fileApi.getFileText(
- this.myState.subfolder + '/' + this.myState.yamlConfig
- )
+ // might be a project config:
+ const filename =
+ this.myState.yamlConfig.indexOf('/') > -1
+ ? this.myState.yamlConfig
+ : this.myState.subfolder + '/' + this.myState.yamlConfig
+
+ const text = await this.myState.fileApi.getFileText(filename)
this.vizDetails = YAML.parse(text)
} catch (err) {
const e = err as any
@@ -619,7 +629,6 @@ class XyHexagons extends Vue {
try {
let filename = `${this.myState.subfolder}/${this.vizDetails.file}`
-
await this.parseCSVFile(filename)
} catch (e) {
console.error(e)
@@ -637,7 +646,7 @@ globalStore.commit('registerPlugin', {
kebabName: 'xy-hexagons',
prettyName: 'XY Aggregator',
description: 'Collects XY data into geographic hexagons',
- filePatterns: ['viz-xy*.y?(a)ml', '*output_trips.csv?(.gz)'],
+ filePatterns: ['**/viz-xy*.y?(a)ml', '*output_trips.csv?(.gz)'],
component: XyHexagons,
} as VisualizationPlugin)
diff --git a/src/styles.scss b/src/styles.scss
index b677fbeb..a00cf1c7 100644
--- a/src/styles.scss
+++ b/src/styles.scss
@@ -39,7 +39,7 @@ $dashboardWidth: 70rem;
--bgTabBanner: linear-gradient(150deg, #345be6, #29d299);
--text: #363636;
--textBold: #1d3355;
- --textFancy: #1d3355;
+ --textFancy: #564c9d;
--textPale: #777777;
--textVeryPale: #bbbbcc;
--link: #196096;
diff --git a/src/views/DashBoard.vue b/src/views/DashBoard.vue
index c6b00f34..c4233de8 100644
--- a/src/views/DashBoard.vue
+++ b/src/views/DashBoard.vue
@@ -41,8 +41,10 @@
:datamanager="datamanager"
:style="{opacity: opacity[card.id]}"
:cardId="card.id"
+ :allConfigFiles="allConfigFiles"
@isLoaded="handleCardIsLoaded(card)"
@dimension-resizer="setDimensionResizer"
+ @titles="setCardTitles(card, $event)"
)
@@ -52,7 +54,7 @@ import { Vue, Component, Watch, Prop } from 'vue-property-decorator'
import YAML from 'yaml'
import HTTPFileSystem from '@/js/HTTPFileSystem'
-import { FileSystemConfig } from '@/Globals'
+import { FileSystemConfig, YamlConfigs } from '@/Globals'
import TopSheet from '@/components/TopSheet/TopSheet.vue'
import charts, { plotlyCharts } from '@/charts/allCharts'
import DashboardDataManager from '@/js/DashboardDataManager'
@@ -78,6 +80,7 @@ export default class VueComponent extends Vue {
@Prop({ required: false }) private config!: any
@Prop({ required: false }) private zoomed!: boolean
@Prop({ required: true }) private datamanager!: DashboardDataManager
+ @Prop({ required: true }) private allConfigFiles!: YamlConfigs
private fileSystemConfig!: FileSystemConfig
private fileApi!: HTTPFileSystem
@@ -119,6 +122,16 @@ export default class VueComponent extends Vue {
window.removeEventListener('resize', this.resizeAllCards)
}
+ /**
+ * This only gets triggered when a topsheet has some titles.
+ * Remove the dashboard titles and use the ones from the topsheet.
+ */
+ private setCardTitles(card: any, event: any) {
+ console.log(card, event)
+ card.title = event
+ card.description = ''
+ }
+
private resizeAllCards() {
for (const row of this.rows) {
for (const card of row) {
@@ -347,6 +360,7 @@ export default class VueComponent extends Vue {
.dash-card {
transition: opacity 0.5s;
+ overflow-x: hidden;
}
@media only screen and (max-width: 50em) {
diff --git a/src/views/FolderBrowser.vue b/src/views/FolderBrowser.vue
index f1dbf1ed..aabb7cd5 100644
--- a/src/views/FolderBrowser.vue
+++ b/src/views/FolderBrowser.vue
@@ -116,7 +116,7 @@ import globalStore from '@/store'
import plugins from '@/plugins/pluginRegistry'
import TabbedDashboardView from '@/views/TabbedDashboardView.vue'
import HTTPFileSystem from '@/js/HTTPFileSystem'
-import { BreadCrumb, VisualizationPlugin, FileSystemConfig } from '@/Globals'
+import { BreadCrumb, FileSystemConfig, YamlConfigs } from '@/Globals'
import TopsheetsFinder from '@/components/TopsheetsFinder/TopsheetsFinder.vue'
const allComponents = Object.assign({ TopsheetsFinder }, plugins)
@@ -131,6 +131,9 @@ export default class VueComponent extends Vue {
@Prop({ required: true })
private root!: string
+ @Prop({ required: true })
+ private allConfigFiles!: YamlConfigs
+
private globalState = globalStore.state
private mdRenderer = new markdown()
@@ -189,7 +192,6 @@ export default class VueComponent extends Vue {
// save them!
globalStore.commit('setBreadCrumbs', crumbs)
-
return crumbs
}
@@ -228,15 +230,10 @@ export default class VueComponent extends Vue {
@Watch('xsubfolder')
private updateRoute() {
- // console.log({ xsubfolder: this.xsubfolder, xproject: this.root })
-
- // why would this be here, don't remember
- // if (!this.$route.name) return
-
const svnProject = this.getFileSystem(this.root)
this.myState.svnProject = svnProject
- this.myState.subfolder = this.xsubfolder || '' // this.$route.params.pathMatch ? this.$route.params.pathMatch : ''
+ this.myState.subfolder = this.xsubfolder || ''
if (!this.myState.svnProject) return
this.myState.svnRoot = new HTTPFileSystem(this.myState.svnProject)
@@ -292,7 +289,6 @@ export default class VueComponent extends Vue {
for (const viz of this.globalState.visualizationTypes.values()) {
// filter based on file matching
const matches = micromatch(this.myState.files, viz.filePatterns)
-
for (const file of matches) {
// add thumbnail for each matching file
this.myState.vizes.push({ component: viz.kebabName, config: file, title: '◆' })
@@ -366,7 +362,6 @@ export default class VueComponent extends Vue {
this.myState.isLoading = true
this.myState.errorStatus = ''
this.myState.files = []
- // this.myState.folders = []
try {
const folderContents = await this.myState.svnRoot.getDirectory(this.myState.subfolder)
@@ -375,9 +370,19 @@ export default class VueComponent extends Vue {
const folders = folderContents.dirs.filter((f) => !f.startsWith('.')).sort()
const files = folderContents.files.filter((f) => !f.startsWith('.')).sort()
+ // Also show any project-level viz thumbnails from other folders
+ // (but, ensure that files in this folder supercede any project viz files
+ // with the same name)
+ const mergedFilesAndVizes = Object.assign({}, this.allConfigFiles.vizes)
+ for (const file of files) {
+ mergedFilesAndVizes[file] = file
+ }
+
+ const allVizes = Object.values(mergedFilesAndVizes)
+
this.myState.errorStatus = ''
this.myState.folders = folders
- this.myState.files = files
+ this.myState.files = allVizes
} catch (err) {
// Bad things happened! Tell user
const e = err as any
diff --git a/src/views/TabbedDashboardView.vue b/src/views/TabbedDashboardView.vue
index 6a552e39..f13e1896 100644
--- a/src/views/TabbedDashboardView.vue
+++ b/src/views/TabbedDashboardView.vue
@@ -22,12 +22,14 @@
:config="dashboards[activeTab]"
:datamanager="dashboardDataManager"
:zoomed="isZoomed"
+ :allConfigFiles="allConfigFiles"
@zoom="handleZoom"
)
folder-browser(v-if="activeTab && activeTab === 'FILE__BROWSER'"
:root="root"
:xsubfolder="xsubfolder"
+ :allConfigFiles="allConfigFiles"
@navigate="onNavigate"
)
@@ -35,10 +37,9 @@