Skip to content

Commit

Permalink
Activity for rule builder imports.
Browse files Browse the repository at this point in the history
  • Loading branch information
jmchilton committed Jan 7, 2025
1 parent 0e14173 commit ac59323
Show file tree
Hide file tree
Showing 10 changed files with 141 additions and 56 deletions.
59 changes: 55 additions & 4 deletions client/src/components/Collections/BuildFileSetWizard.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import { BCardGroup } from "bootstrap-vue";
import { computed, ref } from "vue";
import { getGalaxyInstance } from "@/app";
import { attemptCreate, type CollectionCreatorComponent } from "@/components/Collections/common/useCollectionCreator";
import { rawToTable } from "@/components/Collections/tables";
import { useWizard } from "@/components/Common/Wizard/useWizard";
import { useToolRouting } from "@/composables/route";
Expand All @@ -18,6 +20,7 @@ import SourceFromDatasetAsTable from "./wizard/SourceFromDatasetAsTable.vue";
import SourceFromPastedData from "./wizard/SourceFromPastedData.vue";
import SourceFromRemoteFiles from "./wizard/SourceFromRemoteFiles.vue";
import GenericWizard from "@/components/Common/Wizard/GenericWizard.vue";
import RuleCollectionBuilder from "@/components/RuleCollectionBuilder.vue";
const isBusy = ref<boolean>(false);
const { pasteData, tabularDatasetContents, uris, setRemoteFilesFolder, onFtp, setDatasetContents, setPasteTable } =
Expand All @@ -26,17 +29,20 @@ const { pasteData, tabularDatasetContents, uris, setRemoteFilesFolder, onFtp, se
interface Props {
fileSourcesConfigured: boolean;
ftpUploadSite?: string;
mode: "uploadModal" | "standalone";
}
const props = defineProps<Props>();
const ruleState = ref(false);
const creatingWhat = ref<RulesCreatingWhat>("datasets");
const creatingWhatTitle = computed(() => {
return creatingWhat.value == "datasets" ? "Datasets" : "Collections";
});
const sourceInstructions = computed(() => {
return `${creatingWhatTitle.value} can be created from a set or files, URIs, or existing datasets.`;
});
const collectionCreator = ref<CollectionCreatorComponent | undefined>();
const sourceFrom = ref<RulesSourceFrom>("remote_files");
Expand Down Expand Up @@ -65,7 +71,7 @@ const wizard = useWizard({
},
"paste-data": {
label: "Paste data",
instructions: "Paste data containing URIs and optional extra metadata.",
instructions: "Paste data (or drop file) containing URIs and optional extra metadata.",
isValid: () => sourceFrom.value === "pasted_table" && pasteData.value.length > 0,
isSkippable: () => sourceFrom.value !== "pasted_table",
},
Expand All @@ -75,6 +81,13 @@ const wizard = useWizard({
isValid: () => sourceFrom.value === "dataset_as_table" && tabularDatasetContents.value.length > 0,
isSkippable: () => sourceFrom.value !== "dataset_as_table",
},
"rule-builder": {
label: "Specify Rules",
instructions: "Use this form to describe rules for importing",
isValid: () => ruleState.value,
isSkippable: () => props.mode == "uploadModal",
width: "100%",
},
});
const importButtonLabel = computed(() => {
Expand All @@ -85,7 +98,7 @@ const importButtonLabel = computed(() => {
}
});
const emit = defineEmits(["dismiss"]);
const emit = defineEmits(["dismiss", "created"]);
type SelectionType = "raw" | "remote_files";
type ElementsType = RemoteFile[] | string[][];
Expand All @@ -101,8 +114,7 @@ interface Entry {
selectionType: SelectionType;
}
function launchRuleBuilder() {
const Galaxy = getGalaxyInstance();
const ruleBuilderModalEntryProps = computed(() => {
let elements: ElementsType | undefined = undefined;
let selectionType: SelectionType = "raw";
if (sourceFrom.value == "remote_files") {
Expand All @@ -119,12 +131,31 @@ function launchRuleBuilder() {
selectionType: selectionType,
elements: elements,
};
return entry;
});
const ruleBuilderElements = computed(() => {
const builderProps = ruleBuilderModalEntryProps.value;
let elements;
if (builderProps.elements) {
elements = builderProps.elements;
} else {
elements = rawToTable(builderProps.content || "");
}
return elements;
});
function launchRuleBuilder() {
const Galaxy = getGalaxyInstance();
const entry = ruleBuilderModalEntryProps.value;
Galaxy.currHistoryPanel.buildCollectionFromRules(entry, null, true);
}
function submit() {
if (sourceFrom.value == "collection") {
routeToTool("__APPLY_RULES__");
} else if (props.mode == "standalone") {
attemptCreate(collectionCreator);
} else {
launchRuleBuilder();
}
Expand All @@ -138,6 +169,15 @@ function setCreatingWhat(what: RulesCreatingWhat) {
function setSourceForm(newValue: RulesSourceFrom) {
sourceFrom.value = newValue;
}
function onRuleState(newRuleState: boolean) {
ruleState.value = newRuleState;
}
function onRuleCreate() {
// axios response data for job currently sent, not really used but wanted to document what is available.
emit("created");
}
</script>

<template>
Expand Down Expand Up @@ -165,5 +205,16 @@ function setSourceForm(newValue: RulesSourceFrom) {
<div v-else-if="wizard.isCurrent('select-dataset')">
<SelectDataset @onChange="setDatasetContents" />
</div>
<div v-else-if="wizard.isCurrent('rule-builder')" style="width: 100%">
<RuleCollectionBuilder
ref="collectionCreator"
grid-implementation="ag"
:import-type="creatingWhat"
:elements-type="ruleBuilderModalEntryProps.selectionType"
:initial-elements="ruleBuilderElements"
mode="wizard"
@onCreate="onRuleCreate"
@validInput="onRuleState" />
</div>
</GenericWizard>
</template>
35 changes: 7 additions & 28 deletions client/src/components/Collections/ListWizard.vue
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,11 @@ import { useCollectionBuilderItemSelection } from "@/stores/collectionBuilderIte
import { errorMessageAsString } from "@/utils/simple-error";
import { useCollectionCreation } from "./common/useCollectionCreation";
import { type SupportedPairedOrPairedBuilderCollectionTypes } from "./common/useCollectionCreator";
import {
attemptCreate,
type CollectionCreatorComponent,
type SupportedPairedOrPairedBuilderCollectionTypes,
} from "./common/useCollectionCreator";
import { type WhichListBuilder } from "./ListWizard/types";
import { autoPairWithCommonFilters } from "./pairing";
Expand All @@ -40,9 +44,6 @@ const creationError = ref<string | null>(null);
const collectionCreated = ref(false);
type InferrableBuilder = "list" | "list:paired";
type CollectionCreatorComponent =
| InstanceType<typeof ListCollectionCreator>
| InstanceType<typeof PairedOrUnpairedListCollectionCreator>;
const collectionCreator = ref<CollectionCreatorComponent>();
const { selectedItems } = storeToRefs(store);
Expand Down Expand Up @@ -155,26 +156,15 @@ const pairedListType = computed(() => {
return whichBuilder.value == "list:paired_or_unpaired" ? "list:paired_or_unpaired" : "list:paired";
});
async function attemptCreate(creator: CollectionCreatorComponent) {
// fight typing to workaround https://github.com/vuejs/core/issues/10077
interface HasAttemptCreate {
attemptCreate: () => Promise<void>;
}
(creator as unknown as HasAttemptCreate).attemptCreate();
}
async function submit() {
if (collectionCreator.value) {
attemptCreate(collectionCreator.value);
attemptCreate(collectionCreator);
}
}
async function onCreate(payload: CreateNewCollectionPayload) {
try {
const data = await createHistoryDatasetCollectionInstanceFull(payload);
console.log(data);
console.log("collection created!");
await createHistoryDatasetCollectionInstanceFull(payload);
collectionCreated.value = true;
} catch (e) {
creationError.value = errorMessageAsString(e);
Expand Down Expand Up @@ -213,18 +203,9 @@ function goToAutoPairing() {
wizard.goTo("auto-pairing");
}
function onRuleCreate() {
return 3;
}
function onRuleCancel() {
return 3;
}
const ruleState = ref(false);
function onRuleState(newRuleState: boolean) {
console.log("in on Rule state...");
ruleState.value = newRuleState;
}
</script>
Expand Down Expand Up @@ -288,8 +269,6 @@ function onRuleState(newRuleState: boolean) {
elements-type="datasets"
:initial-elements="selectedItems || []"
mode="wizard"
:oncreate="onRuleCreate"
:oncancel="onRuleCancel"
@onAttemptCreate="ruleOnAttemptCreate"
@validInput="onRuleState" />
</div>
Expand Down
22 changes: 21 additions & 1 deletion client/src/components/Collections/common/useCollectionCreator.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import { computed, ref, watch } from "vue";
import { computed, type Ref, ref, unref, watch } from "vue";

import { type HistoryItemSummary } from "@/api";
import { type CollectionElementIdentifiers, type CreateNewCollectionPayload } from "@/api/datasetCollections";
import type RuleCollectionBuilder from "@/components/RuleCollectionBuilder.vue";
import STATES from "@/mvc/dataset/states";
import localize from "@/utils/localization";

import type ListCollectionCreator from "./ListCollectionCreator.vue";
import type PairedOrUnpairedListCollectionCreator from "./PairedOrUnpairedListCollectionCreator.vue";
import { useCollectionCreation } from "./useCollectionCreation";
import { useExtensionFiltering } from "./useExtensionFilter";

Expand All @@ -28,6 +31,23 @@ export type SupportedPairedOrPairedBuilderCollectionTypes =
| "list:list"
| "list:list:paired";

export type CollectionCreatorComponent =
| InstanceType<typeof ListCollectionCreator>
| InstanceType<typeof PairedOrUnpairedListCollectionCreator>
| InstanceType<typeof RuleCollectionBuilder>;

export async function attemptCreate(creator: CollectionCreatorComponent | Ref<CollectionCreatorComponent | undefined>) {
const creatorValue: CollectionCreatorComponent | undefined = unref(creator);
// fight typing to workaround https://github.com/vuejs/core/issues/10077
interface HasAttemptCreate {
attemptCreate: () => Promise<void>;
}

if (creatorValue) {
(creatorValue as unknown as HasAttemptCreate).attemptCreate();
}
}

export function useCollectionCreator(props: CommonCollectionBuilderProps, emit?: EmitsName) {
const removeExtensions = ref(true);
const hideSourceItems = ref(props.defaultHideSourceItems || false);
Expand Down
11 changes: 10 additions & 1 deletion client/src/components/Common/Wizard/GenericWizard.vue
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,15 @@ const stepsGridColumnsTemplate = computed(() => {
.join(" ") + " max-content"
);
});
const bodyStyle = computed(() => {
const width = props.use.current.value.width;
if (width) {
return { width: width };
} else {
return {};
}
});
</script>

<template>
Expand Down Expand Up @@ -158,7 +167,7 @@ const stepsGridColumnsTemplate = computed(() => {
<div class="step-content">
<span class="h-md step-instructions" v-text="props.use.current.value.instructions" />

<div class="step-body">
<div class="step-body" :style="bodyStyle">
<slot>
<p>
Missing body for step <b>{{ props.use.current.value.label }}</b>
Expand Down
6 changes: 6 additions & 0 deletions client/src/components/Common/Wizard/useWizard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,12 @@ export interface WizardStep {
* This is useful for optional or conditional steps.
*/
isSkippable: () => boolean;

/**
* Hack added by John, someone component in CSS should undo this or come up
* with an alternative that doesn't require this to be set.
*/
hackBodyWidth?: string;
}

/**
Expand Down
24 changes: 16 additions & 8 deletions client/src/components/RuleCollectionBuilder.vue
Original file line number Diff line number Diff line change
Expand Up @@ -553,7 +553,7 @@
)
}}
</RuleModalHeader>
<RuleModalFooter>
<RuleModalFooter v-if="mode == 'modal'">
<b-button class="creator-cancel-btn" tabindex="-1" @click="cancel">{{ l("Close") }}</b-button>
</RuleModalFooter>
</StateDiv>
Expand All @@ -563,7 +563,7 @@
<RuleModalMiddle>
<p class="errormessagelarge">{{ errorMessage }}</p>
</RuleModalMiddle>
<RuleModalFooter>
<RuleModalFooter v-if="mode == 'modal'">
<b-button v-b-tooltip.hover :title="titleCancel" class="creator-cancel-btn" tabindex="-1" @click="cancel">{{
l("Close")
}}</b-button>
Expand Down Expand Up @@ -671,14 +671,16 @@ export default {
required: false,
default: true,
},
// Callbacks sent in by modal code.
// Callbacks sent in by modal code, optional if mode is not modal
oncancel: {
required: true,
required: false,
type: Function,
default: null,
},
oncreate: {
required: true,
required: false,
type: Function,
default: null,
},
ftpUploadSite: {
type: String,
Expand Down Expand Up @@ -1178,7 +1180,6 @@ export default {
}
},
validInput: function (newState) {
console.log("watching validInput....");
this.$emit("validInput", newState);
},
},
Expand Down Expand Up @@ -1372,7 +1373,11 @@ export default {
this.doFullJobCheck(jobId);
} else {
refreshContentsWrapper();
this.oncreate();
this.$emit("onCreate", jobResponse.data);
if (this.oncreate) {
// legacy non-event handling
this.oncreate();
}
}
};
const doJobCheck = () => {
Expand Down Expand Up @@ -1470,7 +1475,10 @@ export default {
this.resetSource();
if (this.state !== "error") {
this.saveRulesFn(this.ruleSourceJson);
this.oncreate();
this.$emit("onCreate");
if (this.oncreate) {
this.oncreate();
}
}
} else {
const Galaxy = getGalaxyInstance();
Expand Down
Loading

0 comments on commit ac59323

Please sign in to comment.