Skip to content
This repository was archived by the owner on May 12, 2026. It is now read-only.
Open
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
7 changes: 2 additions & 5 deletions assets/main.scss
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@


// Import Bulma's core
@import "~bulma/sass/utilities/functions";

// Set colors, overrides etc..
@import 'variables';

@import "variables";

// Import Bulma and Buefy styles
@import "~bulma";
@import "~buefy/src/scss/buefy";
@import "~buefy/src/scss/buefy";
18 changes: 17 additions & 1 deletion components/baseforms/FInput.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<template>
<b-field>
<b-field v-bind="fieldProps">
<template v-if="label" #label>
{{ label }}
<FInfoToolTip :info="info" />
Expand Down Expand Up @@ -44,6 +44,16 @@ export default {
required: false,
default: null,
},
fieldType: {
type: String,
required: false,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think required: false is the default but it's alright that you include this!

default: null,
},
fieldMessage: {
type: String,
required: false,
default: null,
},
},
computed: {
optionalProps() {
Expand All @@ -53,6 +63,12 @@ export default {
this.icon && (optProps.icon = this.icon)
return optProps
},
fieldProps() {
const optProps = {}
this.fieldType && (optProps.type = this.fieldType)
this.fieldMessage && (optProps.message = this.fieldMessage)
return optProps
Comment on lines +66 to +70

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if it might be more straightforward to not have a default on these props and then just make fieldProps the values passed (which would be undefined if not set)? Or does the presence of those keys mess with something even if undefined?

},
},
}
</script>
44 changes: 44 additions & 0 deletions components/xnat2bids/Xnat2BidsBidsmap.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<template>
<fragment>
<b-field>
<b-switch
v-model="value.required"
type="is-info"
@input="updateValue('required', $event)"
>Needs bidsmap file</b-switch
>
</b-field>
<b-field
v-if="value.required"
label="Directory containing the bidsmap file"
>
<b-input
v-model="value.dir"
@input="updateValue('dir', $event)"
></b-input>
</b-field>
<b-field v-if="value.required" label="Bidsmap file">
<b-input
v-model="value.file"
@input="updateValue('file', $event)"
></b-input>
</b-field>
</fragment>
</template>

<script>
export default {
props: {
value: {
type: Object,
required: true,
},
},
methods: {
updateValue(key, val) {
this.value[key] = val
this.$emit('f-bidsmap', this.value)
},
Comment on lines +38 to +41

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The combination of v-model and overwriting the @input event and then changing, but also emitting isn't a combination I've seen much (it kind of murkies a one-way data binding and a two-way). Are the v-models really needed? Could those maybe be just values? Or is there maybe an example/documentation that outlines this pattern that could be linked to in a comment?

},
}
</script>
81 changes: 81 additions & 0 deletions components/xnat2bids/Xnat2BidsSessions.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
<template>
<div class="card-content">
<div v-for="(session, index) in value" :key="index" class="content">
<b-notification :closable="false">
<b-field type="is-warning">
<p class="control">
<span class="button is-static is-link">Participant ID</span>
</p>
<b-input
:value="session.participant_id"
placeholder="135"
@input="updateValue(index, 'participant_id', $event)"
/>
</b-field>
<b-field type="is-warning" message="Required">
<p class="control">
<span class="button is-static">XNAT ACCESSION #</span>
</p>
<b-input
v-model="session.xnat_id"
placeholder="XNAT3_E00013"
@input="updateValue(index, 'xnat_id', $event)"
/>
</b-field>
<b-field label="Include series (empty= ALL series)">
<b-taginput
v-model="session.i_series"
ellipsis
icon="label"
placeholder="Add a series number"
aria-close-label="Delete this tag"
@input="updateValue(index, 'i_series', $event)"
>
</b-taginput>
</b-field>
<b-field label="Exclude series">
<b-taginput
v-model="session.s_series"
ellipsis
icon="label"
placeholder="Add a series number"
aria-close-label="Delete this tag"
@input="updateValue(index, 's_series', $event)"
>
</b-taginput>
</b-field>
</b-notification>
</div>
<b-button type="is-link" outlined @click="addSession">Add Session</b-button>
<b-button
v-if="value.length > 1"
type="is-link"
outlined
@click="removeSession"
>Remove Session</b-button
>
</div>
</template>

<script>
import { mapMutations } from 'vuex'

export default {
props: {
value: {
type: Array,
required: true,
},
},
methods: {
...mapMutations({
addSession: 'xnat2bids/addSession',
removeSession: 'xnat2bids/popSession',
}),
updateValue(index, key, val) {
this.value[index][key] = val

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're updating the prop directly here from the child. Are you experiencing any issue here? I would have thought that you needed to emit the value and then set the prop in the parent component.

Maybe @mcmcgrath13 ?

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, directly updating a prop can cause an infinite render loop. Generally emitting and updating the parent is the safer bet.

this.$emit('f-sessions', this.value)
},
},
}
</script>
187 changes: 15 additions & 172 deletions components/xnat2bids/Xnat2bidsform.vue
Original file line number Diff line number Diff line change
@@ -1,189 +1,32 @@
<template>
<div>
<section>
<b-collapse
:key="0"
class="card"
animation="slide"
:open="isOpen == 0"
@open="isOpen = 0"
>
<div
slot="trigger"
slot-scope="props"
class="card-header"
role="button"
>
<p class="card-header-title">General: Version and paths</p>
<a class="card-header-icon">
<b-icon :icon="props.open ? 'menu-down' : 'menu-up'"> </b-icon>
</a>
</div>
<div class="card-content">
<div class="content">
<b-field label="Version of xnat-tools">
<b-input v-model="version"></b-input>
</b-field>
<b-field
label="Output Path"
type="is-warning"
message="Path required"
>
<b-input
v-model="output_path"
placeholder="/gpfs/data/bnc/shared/bids-export/${USER}"
></b-input>
</b-field>
</div>
</div>
</b-collapse>

<b-collapse
:key="1"
class="card"
animation="slide"
:open="isOpen == 1"
@open="isOpen = 1"
>
<div
slot="trigger"
slot-scope="props"
class="card-header"
role="button"
>
<p class="card-header-title">MRI Sessions</p>
<a class="card-header-icon">
<b-icon :icon="props.open ? 'menu-down' : 'menu-up'"> </b-icon>
</a>
</div>
<div class="card-content">
<div
v-for="(session, index) in sessions"
:key="index"
class="content"
>
<b-notification :closable="false">
<b-field type="is-warning">
<p class="control">
<span class="button is-static is-link">Participant ID</span>
</p>
<b-input v-model="session.participant_id" placeholder="135" />
</b-field>
<b-field type="is-warning" message="Required">
<p class="control">
<span class="button is-static">XNAT ACCESSION #</span>
</p>
<b-input v-model="session.xnat_id" placeholder="XNAT3_E00013" />
</b-field>
<b-field label="Include series (empty= ALL series)">
<b-taginput
v-model="session.i_series"
ellipsis
icon="label"
placeholder="Add a series number"
aria-close-label="Delete this tag"
>
</b-taginput>
</b-field>
<b-field label="Exclude series">
<b-taginput
v-model="session.s_series"
ellipsis
icon="label"
placeholder="Add a series number"
aria-close-label="Delete this tag"
>
</b-taginput>
</b-field>
</b-notification>
</div>
<b-button type="is-link" outlined @click="addSession"
>Add Session</b-button
>
<b-button
v-if="sessions.length > 1"
type="is-link"
outlined
@click="removeSession"
>Remove Session</b-button
>
</div>
</b-collapse>

<b-collapse
:key="2"
class="card"
animation="slide"
:open="isOpen == 1"
@open="isOpen = 1"
>
<div
slot="trigger"
slot-scope="props"
class="card-header"
role="button"
>
<p class="card-header-title">Other flags</p>
<a class="card-header-icon">
<b-icon :icon="props.open ? 'menu-down' : 'menu-up'"> </b-icon>
</a>
</div>
<div class="card-content">
<div class="content">
<b-field>
<b-switch v-model="needs_bidsmap">Needs bidsmap file</b-switch>
</b-field>
<b-field
v-if="needs_bidsmap"
label="Directory containing the bidsmap file"
>
<b-input v-model="bidsmap_dir"></b-input>
</b-field>
<b-field v-if="needs_bidsmap" label="Bidsmap file">
<b-input v-model="bidsmap_file"></b-input>
</b-field>
<b-field grouped label="Flags">
<b-switch v-model="overwrite" type="is-info">Overwrite</b-switch>
<b-switch v-model="verbose" type="is-info">Very Verbose</b-switch>
<b-switch v-model="cleanup" type="is-info">Clean Up</b-switch>
</b-field>
</div>
</div>
</b-collapse>
</section>
<vue-form-json-schema
v-model="xnat2bids"
:schema="schema"
:ui-schema="uiSchema"
></vue-form-json-schema>
</div>
</template>

<script>
import { mapMutations } from 'vuex'
import { mapFields, mapMultiRowFields } from 'vuex-map-fields'
import { mapFields } from 'vuex-map-fields'
import VueFormJsonSchema from 'vue-form-json-schema'
import Xnat2BidsUISchema from '~/data/xnat2bids_ui_schema.json'
import Xnat2BidsSchema from '~/data/basejob_schema.json'

export default {
components: {
'vue-form-json-schema': VueFormJsonSchema,
},
data() {
return {
isOpen: 0,
schema: Xnat2BidsSchema,
uiSchema: Xnat2BidsUISchema,
}
},
computed: {
...mapFields([
'xnat2bids.version',
'xnat2bids.output_path',
'xnat2bids.needs_bidsmap',
'xnat2bids.bidsmap_dir',
'xnat2bids.bidsmap_file',
'xnat2bids.i_series',
'xnat2bids.s_series',
'xnat2bids.overwrite',
'xnat2bids.cleanup',
'xnat2bids.verbose',
]),
...mapMultiRowFields(['xnat2bids.sessions']),
},
methods: {
...mapMutations({
addSession: 'xnat2bids/addSession',
removeSession: 'xnat2bids/popSession',
}),
...mapFields(['xnat2bids']),
},
}
</script>
Loading