Skip to content

Commit

Permalink
Merge pull request #14 from BryonLewis/parameter-defaults
Browse files Browse the repository at this point in the history
Add Parameter Defaults
  • Loading branch information
BryonLewis authored Dec 29, 2023
2 parents e403542 + d9a1f71 commit 6695314
Show file tree
Hide file tree
Showing 12 changed files with 238 additions and 67 deletions.
101 changes: 97 additions & 4 deletions vue-girder-slicer-ui/README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,100 @@
# Vue 3 + Vite
# Girder Slicer UI

This template should help get you started developing with Vue 3 in Vite. The template uses Vue 3 `<script setup>` SFCs, check out the [script setup docs](https://v3.vuejs.org/api/sfc-script-setup.html#sfc-script-setup) to learn more.
This is a vue based component library to interface with the girder slicer CLI plugin.
https://github.com/girder/slicer_cli_web

## Recommended IDE Setup
This Vue component library can be used with the above plugin to list and set values for slicer CLI plugins.

- [VS Code](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar)
# GirderSlicerTasksIntegrated.vue

This is a single component that provies a listing of the tasks as well as an interface to set the paramemter values.

## Customization

### apiURL
The URL of the base girder instance that contains the slicer cli plugin. This defaults to the current host `/api/v1`

### filter
A filter function that can be used to remove tasks from the listing. This will be run on every task that is returned from the `/slicer_cli_web/cli` endpoint. It takes a function of the type `(item: SlicerTask) => boolean` where returning true will display the task and returning false will filter out the task.

```
export interface SlicerTask {
_id: string;
description: string;
image: string;
name: string;
type: string;
}
```

### defaults

A function that iterates through every task parameter and enables setting default values.
`(item: XMLParameters) => undefined | null | XMLParameters`
```
export interface XMLParameters {
type: ParamSlicerType;
slicerType: ParamGUIType;
title: string;
description: string;
channel?: 'input' | 'output';
id: string;
value?: XMLBaseValue;
values?: XMLBaseValue[];
constraints?: {min?: XMLBaseValue; max?: XMLBaseValue; step?: XMLBaseValue};
defaultValue?: XMLBaseValue;
// Extra
fileValue?: {
girderId: string; // item/folder Id for the selected item
name: string; //File Name for display purposes
parentId: string; // Parent folder to open when using DataBrowser
regExp?: boolean | undefined; // When selecting multiple the regExp pattern
fileId?: string | undefined; // fileId used
}; // Added to handle files
required?: boolean;
extensions?: string | undefined;
reference?: string | undefined;
defaultNameMatch?: string | undefined;
defaultPathMatch?: string | undefined;
defaultRelativePath?: string | undefined;
multiple?: boolean;
datalist?: boolean;
shapes?: string | undefined;
error?: string | undefined; // Used to display errors
}
```
You can take the XMLParameter information and set a default `fileValue` or default `value | values` to indicate what it should be.
I.E:
```
(item: XMLParamemters) => {
if (item.channel == 'input' and item.type === 'file') {
const updatedItem = {...item}
item.fileValue = {
fileId: '6433f9123b271b58c749ddbc',
girderId: '6433f9123b271b58c749ddbb',
name: 'SampleVideo.mp4',
parentId: '6433f9113b271b58c749ddb6',
regExp: false,
}
}
}
```
This is used to set default values.

## Color Customization

There are some global css variables that are used to set the colors used in the system:
```
:root {
--gsu-color-primary: rgb(59, 130, 246);
--gsu-color-secondary: #000;
--gsu-color-link: rgb(56, 189, 248);
--gsu-color-text: #dcdcdc;
--gsu-color-muted-text: #d6d6d692;
--gsu-color-background: rgb(75, 85, 99);
--gsu-background-muted: rgb(107, 114, 128);
--gsu-color-highlight: rgb(250, 204, 21);
--gsu-color-selected: rgb(250, 204, 21):
}
```
These variables can be modified to change the visual styling of the system.
34 changes: 32 additions & 2 deletions vue-girder-slicer-ui/src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import GirderSlicerTasksIntegrated from './components/GriderSlicerTasksIntegrate
import DataBrowser from './components/FileBrowser/DataBrowser.tw.vue';
import Modal from './components/FileBrowser/Modal.tw.vue';
import type { GirderModel } from './girderTypes';
import { XMLParameters } from './parser/parserTypes';
import { SlicerTask } from './api/girderSlicerApi';
export default defineComponent({
Expand Down Expand Up @@ -39,11 +41,39 @@ export default defineComponent({
return {valid: false, msg: 'Item needs to be of type jpg'}
}
};
const chanelDefaults = (item: XMLParameters) => {
if (item.channel === 'input' && item.type === 'file') {
item.fileValue = {
fileId: '6433f9123b271b58c749ddbc',
girderId: '6433f9123b271b58c749ddbb',
name: 'SampleVideo.mp4',
parentId: '6433f9113b271b58c749ddb6',
regExp: false,
}
return item;
}
if (item.channel === 'output' && item.type === 'new-file') {
item.fileValue = {
fileId: undefined,
girderId: '6433f9113b271b58c749ddb6',
name: 'SampleFile.json',
parentId: '6433f9113b271b58c749ddb6',
regExp: false,
}
return item;
}
}
const filter = (item: SlicerTask) => item.image.includes('dive');
return {
selected,
select,
showBrowser,
validate,
chanelDefaults,
filter,
};
},
Expand Down Expand Up @@ -72,9 +102,9 @@ export default defineComponent({
type="file"
@close="showBrowser=false"
/> -->
<girder-slicer-tasks-integrated />
<girder-slicer-tasks-integrated :defaults="chanelDefaults" :filter="filter" />
<!-- <girder-slicer-task-menu /> -->
<!-- <girder-slicer-task-button @selected="select($event)" colorMode="dark" /> -->
<!-- <girder-slicer-task-button @selected="select($event)" /> -->
</div>
</div>
</div>
Expand Down
10 changes: 9 additions & 1 deletion vue-girder-slicer-ui/src/api/girderSlicerApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,19 @@ export interface JobResponse {
type: string;
}

export interface SlicerTask {
_id: string;
description: string;
image: string;
name: string;
type: string;
}


const fileTypes = ['file', 'directory', 'image', 'item', 'multi', 'new-file'];
const fileImageItem = ['file', 'image', 'item', 'new-file'];
const useGirderSlicerApi = (girderRest: RestClient) => {
const getSlicerList = async (_filter?: string) => {
const getSlicerList = async () => {
return girderRest.get<SlicerImage[]>('slicer_cli_web/cli');
}
const getSlicerXML = async(id: string) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,6 @@ export default defineComponent({
type: String,
default: "",
},
colorMode: {
type: String,
default: undefined,
},
},
setup(props, { emit }) {
const girderRest = new RestClient({ apiRoot: props.apiUrl });
Expand Down Expand Up @@ -112,7 +108,7 @@ export default defineComponent({
});
</script>
<template>
<div :class="{dark: colorMode === 'dark'}">
<div>
<on-click-outside @trigger="clicked = false">
<div v-if="loggedIn" class="dropdown inline-block relative w-56">
<button
Expand Down
47 changes: 30 additions & 17 deletions vue-girder-slicer-ui/src/components/GirderSlicerTaskCard.tw.vue
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,10 @@ export default defineComponent({
type: String as PropType<string | null>,
default: '64e8aff6072d5e5fbb8719aa'
},
colorMode: {
type:String,
default: undefined
},
defaults: {}
defaults: {
type: Function as PropType<(item: XMLParameters) => undefined | null | XMLParameters>,
default: (_item: XMLParameters) => undefined,
}
},
setup(props, { emit }) {
const girderRest = new RestClient({apiRoot: props.apiUrl});
Expand All @@ -38,7 +37,32 @@ export default defineComponent({
const getData = async () => {
if (props.taskId) {
const response = await slicerApi.getSlicerXML(props.taskId);
result.value = parse(response.data);
const parseParams = parse(response.data);
// We need to assign default values if they exists
const updateParams: {panelIndex: number, groupIndex: number, parameterIndex: number, value: XMLParameters}[] = [];
parseParams.panels.forEach((panel, panelIndex) => {
panel.groups.forEach((group, groupIndex) => {
group.parameters.forEach((parameter, parameterIndex) => {
const paramResult = props.defaults(parameter);
if (paramResult && parseParams) {
// Reset the parameter
updateParams.push({
panelIndex,
groupIndex,
parameterIndex,
value: paramResult,
});
}
});
});
});
console.log(updateParams);
updateParams.forEach((item) => {
if (parseParams) {
parseParams.panels[item.panelIndex].groups[item.groupIndex].parameters[item.parameterIndex] = item.value;
}
});
result.value = parseParams;
}
}
if (props.taskId) {
Expand Down Expand Up @@ -83,7 +107,6 @@ export default defineComponent({
<div
v-if="result"
class="gsu-card relative flex flex-col min-w-0 rounded break-words border pa-2"
:class="{dark: colorMode === 'dark'}"
>
<div class="flex-auto p-6">
<div class="grid grid-cols-12 gap-4 pb-2">
Expand Down Expand Up @@ -138,16 +161,6 @@ export default defineComponent({
/>
</div>
</div>
<div v-else-if="!loggedIn">
<div class="gsu-card relative flex flex-col min-w-0 rounded break-words">
<div
class="relative px-3 py-3 mb-4 border rounded text-yellow-darker border-yellow-dark bg-yellow-lighter"
role="warning"
>
<h4>User Not Logged In. Cannot display Task information.</h4>>
</div>
</div>
</div>
</template>
<style scoped>
</style>
25 changes: 13 additions & 12 deletions vue-girder-slicer-ui/src/components/GirderSlicerTaskMenu.tw.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@
import { Ref, computed, defineComponent, onMounted, ref } from "vue";
import { extractImageInfo } from "../utils";
import RestClient from "../api/girderRest";
import { useGirderSlicerApi } from "../api/girderSlicerApi";
import { SlicerImage, useGirderSlicerApi } from "../api/girderSlicerApi";
import { mdiAlert, mdiChevronDown, mdiChevronRight } from "@mdi/js";
import SvgIcon from "@jamescoyle/vue-icon";
import { cloneDeep } from 'lodash';
import { PropType } from "vue/types/v3-component-props";
interface TaskInfo {
tag: string;
Expand All @@ -32,12 +33,8 @@ export default defineComponent({
default: "api/v1",
},
filter: {
type: String,
default: "",
},
colorMode: {
type: String,
default: undefined,
type: Function as PropType<(task: SlicerImage) => boolean>,
default: (_task: SlicerImage) => true,
},
},
setup(props, { emit }) {
Expand All @@ -49,9 +46,10 @@ export default defineComponent({
const getData = async () => {
try {
const response = await slicerApi.getSlicerList();
const filtered = response.data.filter((task) => props.filter(task));
// ground items by their image
const taskHierarchy: TaskHierarchy = {};
response.data.forEach((task) => {
filtered.forEach((task) => {
// Lets get the base image name
const imageInfo = extractImageInfo(task.image);
if (imageInfo) {
Expand Down Expand Up @@ -136,7 +134,7 @@ export default defineComponent({
});
</script>
<template>
<div :class="{dark: colorMode === 'dark'}">
<div>
<div v-if="loggedIn">
<ul
class="text-textColor"
Expand Down Expand Up @@ -201,9 +199,12 @@ export default defineComponent({
</li>
</ul>
</div>
<div v-else>
Error
<svg-icon type="mdi" :path="mdiAlert" :size="30" class="pb-1" />
<div v-else class="mx-6">
<span>
Error
<svg-icon style="display:inline" type="mdi" color="orange" :path="mdiAlert" :size="30" class="pb-1" />
</span>
<div>The User is not logged in.</div>
</div>
</div>
</template>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import { defineComponent, ref } from "vue";
import SvgIcon from "@jamescoyle/vue-icon";
import Modal from './FileBrowser/Modal.tw.vue';
import GirderSlicerTaskMenu from "./GirderSlicerTaskMenu.tw.vue";
import { SlicerImage } from "../api/girderSlicerApi";
import { PropType } from "vue/types/v3-component-props";
export default defineComponent({
components: {
Expand All @@ -16,12 +18,8 @@ export default defineComponent({
default: "api/v1",
},
filter: {
type: String,
default: "",
},
colorMode: {
type: String,
default: undefined,
type: Function as PropType<(task: SlicerImage) => boolean>,
default: (_task: SlicerImage) => true,
},
},
setup(_props, { emit }) {
Expand Down Expand Up @@ -58,7 +56,6 @@ export default defineComponent({
<template slot="body">
<GirderSlicerTaskMenu
:api-url="apiUrl"
:color-mode="colorMode"
:filter="filter"
@selected="processSelected($event)"
/>
Expand Down
Loading

0 comments on commit 6695314

Please sign in to comment.