Skip to content

Commit

Permalink
Convert components to typescript
Browse files Browse the repository at this point in the history
  • Loading branch information
guerler committed Nov 6, 2024
1 parent 26fe4f1 commit a259c0a
Show file tree
Hide file tree
Showing 13 changed files with 295 additions and 243 deletions.
15 changes: 15 additions & 0 deletions public/galaxy-charts.xml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,21 @@
<type>spec_type</type>
</specs>
<settings>
<input>
<label>My Data Column Label</label>
<help>My Data ColumnHelp</help>
<name>my_data_column_name</name>
<type>data_column</type>
</input>
<input>
<label>My Float Label</label>
<help>My Float Help</help>
<name>my_float_name</name>
<type>float</type>
<value>1</value>
<min>0</min>
<max>100</max>
</input>
<input>
<label>Setting: Text</label>
<name>setting_text</name>
Expand Down
4 changes: 2 additions & 2 deletions src/components/ApiStatus.vue
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
<script setup>
<script setup lang="ts">
import { ref } from "vue";
import { CheckCircleIcon, ExclamationCircleIcon } from "@heroicons/vue/24/outline";
import { NIcon, NTooltip } from "naive-ui";
import { GalaxyApi } from "@/api/client";
const props = defineProps({});
defineProps({});
const version = ref("...");
Expand Down
78 changes: 39 additions & 39 deletions src/components/GalaxyCharts.vue
Original file line number Diff line number Diff line change
@@ -1,51 +1,51 @@
<script setup>
<script setup lang="ts">
import { computed, ref, nextTick, defineProps, defineEmits } from "vue";
import { ArrowPathIcon, ChevronDoubleLeftIcon } from "@heroicons/vue/24/outline";
import SidePanel from "@/components/SidePanel.vue";
import { parsePlugin } from "@/utilities/parsePlugin";
import { computed, ref, nextTick } from "vue";
import { NAlert, NFloatButton, NIcon } from "naive-ui";
import { datasetsGetUrl } from "@/api/datasets";
import { parseIncoming } from "@/utilities/parseIncoming";
import { useConfigStore } from "@/store/configStore";
// props
const props = defineProps({
config: {
type: Object,
default: () => {},
},
xml: {
type: String,
required: true,
},
});
// Define props with TypeScript
interface Config {
credentials?: string;
dataset_id?: string;
dataset_url?: string;
}
const props = defineProps<{
config: Config;
xml: string;
}>();
// references
const collapsePanel = ref(false);
const datasetUrl = ref(null);
const description = ref(null);
const errorMessage = ref("");
const html = ref(null);
const isLoading = ref(true);
const logo = ref(null);
const name = ref("");
const settingInputs = ref([]);
const settingValues = ref({});
const specValues = ref({});
const trackInputs = ref([]);
const trackValues = ref([]);
// References with reactive types
const collapsePanel = ref<boolean>(false);
const datasetUrl = ref<string | null>(null);
const description = ref<string | null>(null);
const errorMessage = ref<string>("");
const html = ref<string | null>(null);
const isLoading = ref<boolean>(true);
const logo = ref<string | null>(null);
const name = ref<string>("");
const settingInputs = ref<Array<Record<string, any>>>([]);
const settingValues = ref<Record<string, any>>({});
const specValues = ref<Record<string, any>>({});
const trackInputs = ref<Array<Record<string, any>>>([]);
const trackValues = ref<Array<Record<string, any>>>([]);
// parse incoming visualization details
// Parse incoming visualization details
const { root, visualizationConfig, visualizationId, visualizationPlugin, visualizationTitle } = parseIncoming(
props.config,
);
// store values in config
// Store values in config store
const configStore = useConfigStore();
configStore.setCredentials(props.config.credentials || "include");
configStore.setRoot(root || "/");
// collect plugin details and parse incoming settings
// Collect plugin details and parse incoming settings
parsePlugin(props.xml, visualizationPlugin, visualizationConfig).then(({ plugin, settings, specs, tracks }) => {
description.value = plugin.description;
html.value = plugin.html;
Expand All @@ -59,7 +59,7 @@ parsePlugin(props.xml, visualizationPlugin, visualizationConfig).then(({ plugin,
trackValues.value = tracks;
});
// get visualization dataset id (required)
// Get visualization dataset ID (required)
const datasetId = visualizationConfig.dataset_id;
if (visualizationConfig.dataset_url) {
datasetUrl.value = visualizationConfig.dataset_url;
Expand All @@ -73,26 +73,26 @@ if (visualizationConfig.dataset_url) {
}
}
// determine logo url
// Determine logo URL
const logoUrl = computed(() => logo.value && `${root}${logo.value}`);
// hide panel
// Hide panel condition
const hidePanel = computed(() => settingInputs.value.length === 0 && trackInputs.value.length === 0);
// toggle side panel
async function onToggle() {
// Toggle side panel visibility
async function onToggle(): Promise<void> {
collapsePanel.value = !collapsePanel.value;
await nextTick();
window.dispatchEvent(new Event("resize"));
}
// event handler for updating settings
function updateSettings(newSettings) {
// Event handler for updating settings
function updateSettings(newSettings: Record<string, any>): void {
settingValues.value = { ...newSettings };
}
// event handler for updating tracks
function updateTracks(newTracks) {
// Event handler for updating tracks
function updateTracks(newTracks: Array<Record<string, any>>): void {
trackValues.value = [...newTracks];
}
</script>
Expand Down
89 changes: 55 additions & 34 deletions src/components/InputConditional.vue
Original file line number Diff line number Diff line change
@@ -1,77 +1,98 @@
<script setup>
<script setup lang="ts">
import { NSelect, NSwitch } from "naive-ui";
import InputForm from "@/components/InputForm.vue";
import { computed, ref, watch } from "vue";
import { computed, ref, watch, defineProps, defineEmits, defineModel } from "vue";
import { parseDefaults } from "@/utilities/parseDefaults";
const props = defineProps({
datasetId: {
type: String,
required: true,
},
// Define props with types
const props = defineProps<{
datasetId: string;
input: {
type: Object,
required: true,
},
});
name: string;
cases?: Array<{
value: string;
inputs: Array<{ name: string; value: any }>;
}>;
test_param?: {
name: string;
type: string;
data?: Array<{ label: string; value: string }>;
};
};
}>();
// Define emit with event typing
const emit = defineEmits<{
(event: "update:value", updatedValues: Record<string, any>): void;
}>();
// emit an event when adding or removing repeat blocks
const emit = defineEmits(["update:value"]);
if (!props.input.test_param) {
throw `The conditional '${props.input.name}' is missing a test parameter.`;
}
if (!props.input.cases || props.input.cases.length === 0) {
throw `The conditional '${props.input.name}' is missing a cases.`;
}
// get test parameter
// Get test parameter
const testParam = ref(props.input.test_param);
// get test parameter name
// Get test parameter name and validate it
const testName = testParam.value.name;
if (!testName) {
console.error(`Test parameter has no name: ${props.input.name}.`);
}
// reference current test and conditional values
const currentValue = defineModel("value");
// Reference the model value of the conditional component
const currentValue = defineModel<Record<string, any>>("value");
if (!currentValue.value || !(testName in currentValue.value)) {
console.error(`Test parameter of conditional not available: ${props.input.name}.`, currentValue.value);
}
// reference current test parameter value
const currentTestValue = ref(currentValue.value[testName]);
// Reference current test parameter value
const currentTestValue = ref<string>(currentValue.value && currentValue.value[testName]);
// collect input cases and identify defaults
// Collect input cases and identify defaults
const caseDefaults = computed(() => {
const result = {};
for (const inputCase of props.input.cases) {
result[inputCase.value] = parseDefaults(inputCase.inputs);
result[inputCase.value][testName] = inputCase.value;
const result: Record<string, Record<string, any>> = {};
if (props.input.cases && props.input.cases.length > 0) {
for (const inputCase of props.input.cases) {
result[inputCase.value] = parseDefaults(inputCase.inputs);
result[inputCase.value][testName] = inputCase.value;
}
}
return result;
});
// collect all input cases
// Collect all input cases
const caseInputs = computed(() => {
const result = {};
for (const inputCase of props.input.cases) {
result[inputCase.value] = inputCase.inputs;
const result: Record<string, Array<{ name: string; value: any }>> = {};
if (props.input.cases && props.input.cases.length > 0) {
for (const inputCase of props.input.cases) {
result[inputCase.value] = inputCase.inputs;
}
}
return result;
});
// Current inputs based on selected test value
const currentInputs = computed(() => caseInputs.value[currentTestValue.value]);
// handle conversion of boolean switch values to string for case evaluation
// Handle conversion of boolean switch values to string for case evaluation
const switchTestValue = computed({
get() {
return currentTestValue.value === "true";
},
set(newVal) {
set(newVal: boolean) {
currentTestValue.value = String(newVal);
},
});
// update values if test value changes or conditional input elements are modified
function onUpdate(newValues) {
// Update values if test value changes or conditional input elements are modified
function onUpdate(newValues?: Record<string, any>) {
let updatedValues = { ...caseDefaults.value[currentTestValue.value] };
if (newValues) {
const filteredValues = {};
const filteredValues: Record<string, any> = {};
currentInputs.value.forEach((x) => {
filteredValues[x.name] = newValues[x.name];
});
Expand All @@ -80,7 +101,7 @@ function onUpdate(newValues) {
emit("update:value", updatedValues);
}
// load defaults if test value changes
// Load defaults if test value changes
watch(
() => currentTestValue.value,
() => {
Expand Down
43 changes: 21 additions & 22 deletions src/components/InputData.vue
Original file line number Diff line number Diff line change
@@ -1,37 +1,33 @@
<script setup>
import { ref } from "vue";
import { NSelect } from "naive-ui";
<script setup lang="ts">
import { ref, defineProps, defineModel } from "vue";
import { NSelect, NIcon } from "naive-ui";
import { GalaxyApi } from "@/api/client";
import { CheckCircleIcon, ExclamationCircleIcon } from "@heroicons/vue/24/outline";
import { NIcon } from "naive-ui";
const LIMIT = 100;
const props = defineProps({
extension: {
type: String,
default: "",
},
optional: {
type: Boolean,
default: false,
},
});
// Define props with TypeScript
const props = defineProps<{
extension?: string;
optional: boolean;
}>();
// emit an event when adding or removing repeat blocks
const currentOptions = ref([]);
const currentValue = defineModel("value");
// Define the model
const currentOptions = ref<Array<{ label: string; value: any; disabled?: boolean }>>([]);
const currentValue = defineModel<{ name: string } | null>("value");
const isLoading = ref(false);
const selectValue = ref(null);
const selectValue = ref<any | null>(null);
async function loadDatasets(query) {
// Load datasets based on filters and query
async function loadDatasets(query?: string): Promise<void> {
isLoading.value = true;
try {
const extensionFilter = props.extension ? `q=extension-eq&qv=${props.extension}` : "";
const nameFilter = query ? `q=name-contains&qv=${query}` : "";
const { data } = await GalaxyApi().GET(`/api/datasets?limit=${LIMIT}&${extensionFilter}&${nameFilter}`);
if (data && data.length > 0) {
const options = data.map((x) => ({
const options = data.map((x: { name: string }) => ({
label: x.name,
value: x,
}));
Expand All @@ -41,17 +37,20 @@ async function loadDatasets(query) {
}
currentOptions.value = options;
}
isLoading.value = false;
} catch (err) {
console.log(err);
} finally {
isLoading.value = false;
}
}
function onUpdate() {
// Update the current selection value
function onUpdate(): void {
currentValue.value = selectValue.value;
selectValue.value = null;
}
// Load initial datasets when the component is mounted
loadDatasets();
</script>

Expand Down
Loading

0 comments on commit a259c0a

Please sign in to comment.