Skip to content
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

Add support for single file hubs #4070

Merged
merged 6 commits into from
Nov 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion plugins/data-management/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
"clean": "rimraf dist esm *.tsbuildinfo"
},
"dependencies": {
"@gmod/ucsc-hub": "^0.1.6",
"@gmod/ucsc-hub": "^0.3.0",
"@mui/icons-material": "^5.0.1",
"@mui/x-data-grid": "^6.0.1",
"clsx": "^2.0.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ exports[`renders 1`] = `
aria-hidden="true"
aria-invalid="false"
class="MuiSelect-nativeInput css-yf8vq0-MuiSelect-nativeInput"
name=":r2:"
tabindex="-1"
value="UCSCTrackHubConnection"
/>
Expand Down
83 changes: 82 additions & 1 deletion plugins/data-management/src/AddTrackWidget/model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,24 @@ interface IndexingAttr {
attributes: string[]
exclude: string[]
}

/**
* #stateModel AddTrackModel
*/
export default function f(pluginManager: PluginManager) {
return types
.model('AddTrackModel', {
/**
* #property
*/
id: ElementId,
/**
* #property
*/
type: types.literal('AddTrackWidget'),
/**
* #property
*/
view: types.safeReference(
pluginManager.pluggableMstType('view', 'stateModel'),
),
Expand All @@ -45,34 +58,63 @@ export default function f(pluginManager: PluginManager) {
textIndexingConf: undefined as IndexingAttr | undefined,
}))
.actions(self => ({
/**
* #action
*/
setAdapterHint(obj: string) {
self.adapterHint = obj
},
/**
* #action
*/
setTrackSource(str: string) {
self.trackSource = str
},
/**
* #action
*/
setTextIndexingConf(conf: IndexingAttr) {
self.textIndexingConf = conf
},
/**
* #action
*/
setTextIndexTrack(flag: boolean) {
self.textIndexTrack = flag
},
/**
* #action
*/
setTrackData(obj: FileLocation) {
self.trackData = obj
},
/**
* #action
*/
setIndexTrackData(obj: FileLocation) {
self.indexTrackData = obj
},
/**
* #action
*/
setAssembly(str: string) {
self.altAssemblyName = str
},
/**
* #action
*/
setTrackName(str: string) {
self.altTrackName = str
},
/**
* #action
*/
setTrackType(str: string) {
self.altTrackType = str
},

/**
* #action
*/
clearData() {
self.trackSource = ''
self.altTrackName = ''
Expand All @@ -86,6 +128,9 @@ export default function f(pluginManager: PluginManager) {
},
}))
.views(self => ({
/**
* #getter
*/
get trackAdapter() {
const { trackData, indexTrackData, adapterHint } = self

Expand All @@ -94,13 +139,19 @@ export default function f(pluginManager: PluginManager) {
: undefined
},

/**
* #getter
*/
get trackName() {
return (
self.altTrackName ||
(self.trackData ? getFileName(self.trackData) : '')
)
},

/**
* #getter
*/
get isFtp() {
const { trackData: track, indexTrackData: index } = self
return !!(
Expand All @@ -109,44 +160,71 @@ export default function f(pluginManager: PluginManager) {
)
},

/**
* #getter
*/
get isRelativeTrackUrl() {
// @ts-expect-error
const uri = self.trackData?.uri
return uri ? !isAbsoluteUrl(uri) : false
},
/**
* #getter
*/
get isRelativeIndexUrl() {
// @ts-expect-error
const uri = self.indexTrackData?.uri
return uri ? !isAbsoluteUrl(uri) : false
},
/**
* #getter
*/
get isRelativeUrl() {
return this.isRelativeIndexUrl || this.isRelativeTrackUrl
},

/**
* #getter
*/
get trackHttp() {
// @ts-expect-error
return self.trackData?.uri?.startsWith('http://')
},
/**
* #getter
*/
get indexHttp() {
// @ts-expect-error
return self.indexTrackData?.uri?.startsWith('http://')
},

/**
* #getter
*/
get wrongProtocol() {
return (
window.location.protocol === 'https:' &&
(this.trackHttp || this.indexHttp)
)
},

/**
* #getter
*/
get unsupported() {
return this.trackAdapter?.type === UNSUPPORTED
},

/**
* #getter
*/
get assembly() {
return self.altAssemblyName || self.view.assemblyNames?.[0]
},

/**
* #getter
*/
get trackType() {
return (
self.altTrackType ||
Expand All @@ -157,6 +235,9 @@ export default function f(pluginManager: PluginManager) {
},
}))
.views(self => ({
/**
* #getter
*/
get warningMessage() {
if (self.isFtp) {
return `Warning: JBrowse cannot access files using the ftp protocol`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ exports[`renders nothing with no assembly 1`] = `
class="MuiFormControl-root MuiFormControl-marginDense MuiFormControl-fullWidth MuiTextField-root css-rlnh8o-MuiFormControl-root-MuiTextField-root-searchBox"
>
<label
class="MuiFormLabel-root MuiInputLabel-root MuiInputLabel-formControl MuiInputLabel-animated MuiInputLabel-sizeSmall MuiInputLabel-standard MuiFormLabel-colorPrimary MuiInputLabel-root MuiInputLabel-formControl MuiInputLabel-animated MuiInputLabel-sizeSmall MuiInputLabel-standard css-1s1jvl0-MuiFormLabel-root-MuiInputLabel-root"
class="MuiFormLabel-root MuiInputLabel-root MuiInputLabel-formControl MuiInputLabel-animated MuiInputLabel-sizeSmall MuiInputLabel-standard MuiFormLabel-colorPrimary MuiInputLabel-root MuiInputLabel-formControl MuiInputLabel-animated MuiInputLabel-sizeSmall MuiInputLabel-standard css-11ok34h-MuiFormLabel-root-MuiInputLabel-root"
data-shrink="false"
for=":r0:"
id=":r0:-label"
Expand Down Expand Up @@ -257,7 +257,7 @@ exports[`renders with a couple of categorized tracks 1`] = `
class="MuiFormControl-root MuiFormControl-marginDense MuiFormControl-fullWidth MuiTextField-root css-rlnh8o-MuiFormControl-root-MuiTextField-root-searchBox"
>
<label
class="MuiFormLabel-root MuiInputLabel-root MuiInputLabel-formControl MuiInputLabel-animated MuiInputLabel-sizeSmall MuiInputLabel-standard MuiFormLabel-colorPrimary MuiInputLabel-root MuiInputLabel-formControl MuiInputLabel-animated MuiInputLabel-sizeSmall MuiInputLabel-standard css-1s1jvl0-MuiFormLabel-root-MuiInputLabel-root"
class="MuiFormLabel-root MuiInputLabel-root MuiInputLabel-formControl MuiInputLabel-animated MuiInputLabel-sizeSmall MuiInputLabel-standard MuiFormLabel-colorPrimary MuiInputLabel-root MuiInputLabel-formControl MuiInputLabel-animated MuiInputLabel-sizeSmall MuiInputLabel-standard css-11ok34h-MuiFormLabel-root-MuiInputLabel-root"
data-shrink="false"
for=":r9:"
id=":r9:-label"
Expand Down Expand Up @@ -838,7 +838,7 @@ exports[`renders with a couple of uncategorized tracks 1`] = `
class="MuiFormControl-root MuiFormControl-marginDense MuiFormControl-fullWidth MuiTextField-root css-rlnh8o-MuiFormControl-root-MuiTextField-root-searchBox"
>
<label
class="MuiFormLabel-root MuiInputLabel-root MuiInputLabel-formControl MuiInputLabel-animated MuiInputLabel-sizeSmall MuiInputLabel-standard MuiFormLabel-colorPrimary MuiInputLabel-root MuiInputLabel-formControl MuiInputLabel-animated MuiInputLabel-sizeSmall MuiInputLabel-standard css-1s1jvl0-MuiFormLabel-root-MuiInputLabel-root"
class="MuiFormLabel-root MuiInputLabel-root MuiInputLabel-formControl MuiInputLabel-animated MuiInputLabel-sizeSmall MuiInputLabel-standard MuiFormLabel-colorPrimary MuiInputLabel-root MuiInputLabel-formControl MuiInputLabel-animated MuiInputLabel-sizeSmall MuiInputLabel-standard css-11ok34h-MuiFormLabel-root-MuiInputLabel-root"
data-shrink="false"
for=":r3:"
id=":r3:-label"
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,10 @@ import {
measureGridWidth,
} from '@jbrowse/core/util'
import { autorun, observable } from 'mobx'
import { getRootKeys } from './components/faceted/util'
import { getRootKeys, findNonSparseKeys } from './facetedUtil'

const nonMetadataKeys = ['category', 'adapter', 'description'] as const

function filt(
keys: readonly string[],
rows: Record<string, unknown>[],
cb: (row: Record<string, unknown>, f: string) => unknown,
) {
return keys.filter(f => rows.map(r => cb(r, f)).filter(f => !!f).length > 5)
}

/**
* #stateModel FacetedModel
*/
Expand Down Expand Up @@ -114,9 +106,10 @@ export function facetedStateTreeF() {
/**
* #getter
*/
get trackConfigurations() {
return getParent<{ trackConfigurations: AnyConfigurationModel[] }>(self)
.trackConfigurations
get allTrackConfigurations() {
return getParent<{ allTrackConfigurations: AnyConfigurationModel[] }>(
self,
).allTrackConfigurations
},
}))
.views(self => ({
Expand All @@ -125,10 +118,10 @@ export function facetedStateTreeF() {
*/
get rows() {
const session = getSession(self)
const { trackConfigurations, filterText } = self
const { allTrackConfigurations, filterText } = self
// metadata is spread onto the object for easier access and sorting
// by the mui data grid (it's unable to sort by nested objects)
return trackConfigurations
return allTrackConfigurations
.filter(conf => matches(filterText, conf, session))
.map(track => {
const metadata = readConfObject(track, 'metadata')
Expand All @@ -146,29 +139,43 @@ export function facetedStateTreeF() {
}))

.views(self => ({
/**
* #getter
*/
get filteredNonMetadataKeys() {
return self.showSparse
? nonMetadataKeys
: filt(nonMetadataKeys, self.rows, (r, f) => r[f])
: findNonSparseKeys(nonMetadataKeys, self.rows, (r, f) => r[f])
},

/**
* #getter
*/
get metadataKeys() {
return [...new Set(self.rows.flatMap(row => getRootKeys(row.metadata)))]
},
get filteredMetadataKeys() {
return self.showSparse
? this.metadataKeys
: // @ts-expect-error
filt(this.metadataKeys, self.rows, (r, f) => r.metadata[f])
: findNonSparseKeys(
this.metadataKeys,
self.rows,
// @ts-expect-error
(r, f) => r.metadata[f],
)
},

/**
* #getter
*/
get fields() {
return [
'name',
...this.filteredNonMetadataKeys,
...this.filteredMetadataKeys.map(m => `metadata.${m}`),
]
},
/**
* #getter
*/
get filteredRows() {
const arrFilters = [...self.filters.entries()]
.filter(f => f[1].length > 0)
Expand All @@ -180,9 +187,15 @@ export function facetedStateTreeF() {
},
}))
.actions(self => ({
/**
* #action
*/
setVisible(args: Record<string, boolean>) {
self.visible = args
},
/**
* #action
*/
setWidths(args: Record<string, number | undefined>) {
self.widths = args
},
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
export function findNonSparseKeys(
keys: readonly string[],
rows: Record<string, unknown>[],
cb: (row: Record<string, unknown>, f: string) => unknown,
) {
return keys.filter(f => rows.map(r => cb(r, f)).filter(f => !!f).length > 5)
}

export function getRootKeys(obj: Record<string, unknown>) {
return Object.entries(obj)
.map(([key, val]) => (typeof val === 'string' ? key : ''))
.filter(f => !!f)
}
Loading
Loading