mirror of
https://github.com/galaxyproject/galaxy.git
synced 2026-09-21 13:50:20 +08:00
Merge pull request #18638 from itisAliRH/libraries-modernization-1-directory-dataset-picker
Libraries Modernisation: Directory Dataset Picker
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { BAlert, BFormCheckbox } from "bootstrap-vue";
|
||||
import { computed, type ComputedRef } from "vue";
|
||||
|
||||
import { findDescendants, flattenValues, getAllValues, type Option, type Value } from "./utilities";
|
||||
@@ -11,10 +12,12 @@ const props = withDefaults(
|
||||
value?: Value;
|
||||
options: Array<Option>;
|
||||
multiple: boolean;
|
||||
showIcons?: boolean;
|
||||
}>(),
|
||||
{
|
||||
value: null,
|
||||
multiple: true,
|
||||
showIcons: false,
|
||||
}
|
||||
);
|
||||
|
||||
@@ -91,20 +94,27 @@ function setElementValues(oldArray: string[], newArray: string[], value: string)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div v-if="hasOptions">
|
||||
<b-form-checkbox
|
||||
v-if="multiple"
|
||||
v-localize
|
||||
:checked="selectAllChecked"
|
||||
:indeterminate="selectAllIndeterminate"
|
||||
class="d-inline select-all-checkbox"
|
||||
@change="onSelectAll">
|
||||
Select / Deselect All
|
||||
</b-form-checkbox>
|
||||
<FormDrilldownList
|
||||
:multiple="multiple"
|
||||
:current-value="currentValue"
|
||||
:options="options"
|
||||
:handle-click="handleClick" />
|
||||
<div>
|
||||
<div v-if="hasOptions">
|
||||
<BFormCheckbox
|
||||
v-if="multiple"
|
||||
v-localize
|
||||
:checked="selectAllChecked"
|
||||
:indeterminate="selectAllIndeterminate"
|
||||
class="d-inline select-all-checkbox"
|
||||
@change="onSelectAll">
|
||||
Select / Deselect All
|
||||
</BFormCheckbox>
|
||||
|
||||
<FormDrilldownList
|
||||
:show-icons="showIcons"
|
||||
:multiple="multiple"
|
||||
:current-value="currentValue"
|
||||
:options="options"
|
||||
:handle-click="handleClick" />
|
||||
</div>
|
||||
<div v-else>
|
||||
<BAlert show variant="info" class="mt-2"> No options available. </BAlert>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -7,6 +7,7 @@ defineProps<{
|
||||
currentValue: string[];
|
||||
handleClick: Function;
|
||||
multiple: boolean;
|
||||
showIcons?: boolean;
|
||||
options: Array<Option>;
|
||||
}>();
|
||||
</script>
|
||||
@@ -15,6 +16,7 @@ defineProps<{
|
||||
<div class="ui-drilldown">
|
||||
<div v-for="option in options" :key="option.name" class="descendant-lines">
|
||||
<FormDrilldownOption
|
||||
:show-icons="showIcons"
|
||||
:current-value="currentValue"
|
||||
:handle-click="handleClick"
|
||||
:multiple="multiple"
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import { faCaretDown, faCaretRight, faFile, faFolder, type IconDefinition } from "@fortawesome/free-solid-svg-icons";
|
||||
import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome";
|
||||
import { BFormCheckbox, BFormRadio } from "bootstrap-vue";
|
||||
import { computed, type ComputedRef, onMounted, ref } from "vue";
|
||||
|
||||
@@ -6,12 +8,20 @@ import { getAllValues, type Option } from "./utilities";
|
||||
|
||||
import FormDrilldownList from "./FormDrilldownList.vue";
|
||||
|
||||
const props = defineProps<{
|
||||
interface Props {
|
||||
currentValue: string[];
|
||||
option: Option;
|
||||
handleClick: Function;
|
||||
multiple: boolean;
|
||||
}>();
|
||||
showIcons?: boolean;
|
||||
leafIcon?: IconDefinition;
|
||||
branchIcon?: IconDefinition;
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
leafIcon: () => faFile,
|
||||
branchIcon: () => faFolder,
|
||||
});
|
||||
|
||||
const showChildren = ref(false);
|
||||
|
||||
@@ -43,6 +53,11 @@ function toggleInitialization(): void {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getOptionIcon(option: Option) {
|
||||
return option.leaf ? props.leafIcon : props.branchIcon;
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
toggleInitialization();
|
||||
});
|
||||
@@ -51,22 +66,26 @@ onMounted(() => {
|
||||
<template>
|
||||
<div>
|
||||
<b-button v-if="hasOptions" variant="link" class="btn p-0" @click="toggleChildren">
|
||||
<i v-if="showChildren" class="fa fa-caret-down align-checkbox" />
|
||||
<i v-else class="fa fa-caret-right align-checkbox" />
|
||||
<FontAwesomeIcon v-if="showChildren" :icon="faCaretDown" class="align-checkbox" />
|
||||
<FontAwesomeIcon v-else :icon="faCaretRight" class="align-checkbox" />
|
||||
</b-button>
|
||||
<span v-if="!hasOptions" class="align-indent"></span>
|
||||
<component
|
||||
:is="isComponent"
|
||||
:id="`drilldown-option-${option.name}`"
|
||||
class="drilldown-option d-inline"
|
||||
value="true"
|
||||
:disabled="option.disabled"
|
||||
:checked="isChecked"
|
||||
@change="handleClick(option.value, $event)">
|
||||
<FontAwesomeIcon v-if="props.showIcons" :icon="getOptionIcon(option)" />
|
||||
{{ option.name }}
|
||||
</component>
|
||||
<FormDrilldownList
|
||||
v-if="hasOptions"
|
||||
v-show="showChildren"
|
||||
class="indent"
|
||||
:show-icons="props.showIcons"
|
||||
:current-value="currentValue"
|
||||
:multiple="multiple"
|
||||
:options="option.options"
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
export interface Option {
|
||||
name: string;
|
||||
value: string;
|
||||
leaf?: boolean;
|
||||
fullPath?: string;
|
||||
disabled?: boolean;
|
||||
options: Array<Option>;
|
||||
}
|
||||
|
||||
|
||||
+10
-10
@@ -99,7 +99,7 @@
|
||||
collection-name="Database/Builds"
|
||||
:loading="loadingDbKeys"
|
||||
:items="dbkeys"
|
||||
:current-item-id="selectedDbKey"
|
||||
:current-item="selectedDbKey"
|
||||
@update:selected-item="onSelectedDbKey" />
|
||||
</DbKeyProvider>
|
||||
</b-modal>
|
||||
@@ -116,7 +116,7 @@
|
||||
collection-name="Data Types"
|
||||
:loading="loadingDatatypes"
|
||||
:items="datatypes"
|
||||
:current-item-id="selectedDatatype"
|
||||
:current-item="selectedDatatype"
|
||||
@update:selected-item="onSelectedDatatype" />
|
||||
</DatatypesProvider>
|
||||
</b-modal>
|
||||
@@ -186,8 +186,8 @@ export default {
|
||||
},
|
||||
data: function () {
|
||||
return {
|
||||
selectedDbKey: "?",
|
||||
selectedDatatype: "auto",
|
||||
selectedDbKey: { id: "?", text: "unspecified (?)" },
|
||||
selectedDatatype: { id: "auto", text: "Auto-detect" },
|
||||
selectedTags: [],
|
||||
};
|
||||
},
|
||||
@@ -307,12 +307,12 @@ export default {
|
||||
this.runOnSelection(purgeSelectedContent);
|
||||
},
|
||||
changeDbkeyOfSelected() {
|
||||
this.runOnSelection(changeDbkeyOfSelectedContent, { dbkey: this.selectedDbKey });
|
||||
this.selectedDbKey = "?";
|
||||
this.runOnSelection(changeDbkeyOfSelectedContent, { dbkey: this.selectedDbKey.id });
|
||||
this.selectedDbKey = { id: "?" };
|
||||
},
|
||||
changeDatatypeOfSelected() {
|
||||
this.runOnSelection(changeDatatypeOfSelectedContent, { datatype: this.selectedDatatype });
|
||||
this.selectedDatatype = "auto";
|
||||
this.runOnSelection(changeDatatypeOfSelectedContent, { datatype: this.selectedDatatype.id });
|
||||
this.selectedDatatype = { id: "auto", text: "Auto-detect" };
|
||||
},
|
||||
addTagsToSelected() {
|
||||
this.runOnSelection(addTagsToSelectedContent, { tags: this.selectedTags });
|
||||
@@ -354,10 +354,10 @@ export default {
|
||||
this.$emit("operation-error", { errorMessage, result });
|
||||
},
|
||||
onSelectedDbKey(dbkey) {
|
||||
this.selectedDbKey = dbkey.id;
|
||||
this.selectedDbKey = dbkey;
|
||||
},
|
||||
onSelectedDatatype(datatype) {
|
||||
this.selectedDatatype = datatype.id;
|
||||
this.selectedDatatype = datatype;
|
||||
},
|
||||
|
||||
// collection creation, fires up a modal
|
||||
|
||||
+2
-2
@@ -83,7 +83,7 @@
|
||||
collection-name="Data Types"
|
||||
:loading="loadingDatatypes"
|
||||
:items="datatypes"
|
||||
:current-item-id="dataset.file_ext"
|
||||
:current-item="datatypes?.find((datatype) => datatype.id === dataset.file_ext)"
|
||||
@update:selected-item="onSelectedDatatype" />
|
||||
</DatatypesProvider>
|
||||
<DbKeyProvider
|
||||
@@ -93,7 +93,7 @@
|
||||
collection-name="Database/Builds"
|
||||
:loading="loadingDbKeys"
|
||||
:items="dbkeys"
|
||||
:current-item-id="dataset.genome_build"
|
||||
:current-item="dbkeys?.find((dbkey) => dbkey.id === dataset.genome_build)"
|
||||
@update:selected-item="onSelectedDbKey" />
|
||||
</DbKeyProvider>
|
||||
<b-form-input
|
||||
|
||||
@@ -0,0 +1,366 @@
|
||||
<script setup lang="ts">
|
||||
import {
|
||||
BAlert,
|
||||
BButton,
|
||||
BFormCheckbox,
|
||||
BFormCheckboxGroup,
|
||||
BFormGroup,
|
||||
BFormTextarea,
|
||||
BModal,
|
||||
BTab,
|
||||
BTabs,
|
||||
} from "bootstrap-vue";
|
||||
import { computed, ref, watch } from "vue";
|
||||
|
||||
import { GalaxyApi } from "@/api";
|
||||
import { type Option } from "@/components/Form/Elements/FormDrilldown/utilities";
|
||||
import { type DetailedDatatypes, useDetailedDatatypes } from "@/composables/datatypes";
|
||||
import { Toast } from "@/composables/toast";
|
||||
import { useDbKeyStore } from "@/stores/dbKeyStore";
|
||||
import { errorMessageAsString } from "@/utils/simple-error";
|
||||
|
||||
import FormDrilldown from "@/components/Form/Elements/FormDrilldown/FormDrilldown.vue";
|
||||
import LoadingSpan from "@/components/LoadingSpan.vue";
|
||||
import SingleItemSelector from "@/components/SingleItemSelector.vue";
|
||||
|
||||
const autoExtension = {
|
||||
id: "auto",
|
||||
extension: "auto",
|
||||
text: "Auto-detect",
|
||||
description: `This system will try to detect the file type automatically.
|
||||
If your file is not detected properly as one of the known formats,
|
||||
it most likely means that it has some format problems (e.g., different
|
||||
number of columns on different rows). You can still coerce the system
|
||||
to set your data to the format you think it should be.
|
||||
You can also upload compressed files, which will automatically be decompressed`,
|
||||
descriptionUrl: "",
|
||||
};
|
||||
|
||||
type DbKey = { id: string; text: string };
|
||||
type DbKeyList = DbKey[];
|
||||
|
||||
type RequestData = {
|
||||
path: string;
|
||||
source: string;
|
||||
dbkey: string;
|
||||
encoded_folder_id: string;
|
||||
file_type?: string;
|
||||
preserve_dirs?: boolean;
|
||||
link_data: boolean;
|
||||
space_to_tab: boolean;
|
||||
to_posix_lines: boolean;
|
||||
tag_using_filenames: boolean;
|
||||
};
|
||||
|
||||
interface Props {
|
||||
folderId: string;
|
||||
target: "userdir" | "importdir" | "path";
|
||||
}
|
||||
|
||||
const props = defineProps<Props>();
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: "reload"): void;
|
||||
(e: "onClose"): void;
|
||||
(e: "onSelect", items: RequestData[]): void;
|
||||
}>();
|
||||
|
||||
const dbKeyStore = useDbKeyStore();
|
||||
const { datatypes, datatypesLoading } = useDetailedDatatypes();
|
||||
|
||||
const activeTab = ref(0);
|
||||
const importing = ref(false);
|
||||
const paths = ref<string>("");
|
||||
const options = ref<Option[]>([]);
|
||||
const optionsLoading = ref(false);
|
||||
const selectedDbKey = ref<DbKey>();
|
||||
const dbKeyList = ref<DbKeyList>([]);
|
||||
const errorMessage = ref<string>("");
|
||||
const currentValue = ref<string[]>([]);
|
||||
const preserveOptions = ref<string[]>([]);
|
||||
const extensionsList = ref<DetailedDatatypes[]>([]);
|
||||
const selectedExtension = ref<DetailedDatatypes>(autoExtension);
|
||||
|
||||
const pathMode = computed(() => {
|
||||
return props.target === "path";
|
||||
});
|
||||
const filesMode = computed(() => {
|
||||
return activeTab.value === 0;
|
||||
});
|
||||
const title = computed(() => {
|
||||
return pathMode.value ? "Please enter paths to import" : "Please select folders or files";
|
||||
});
|
||||
const importDisable = computed(() => {
|
||||
if (importing.value) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (pathMode.value) {
|
||||
return paths.value?.length === 0;
|
||||
}
|
||||
|
||||
return currentValue.value?.length === 0;
|
||||
});
|
||||
const okButtonText = computed(() => {
|
||||
const length = currentValue.value?.length || 0;
|
||||
|
||||
return length === 0 ? "Import" : `Import ${length} dataset${length > 1 ? "s" : ""}`;
|
||||
});
|
||||
|
||||
async function fetchOptions() {
|
||||
optionsLoading.value = true;
|
||||
|
||||
const { data, error } = await GalaxyApi().GET("/api/remote_files", {
|
||||
params: {
|
||||
query: {
|
||||
format: "jstree",
|
||||
target: props.target,
|
||||
disable: filesMode.value ? "folders" : "files",
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
options.value = mapDataToOptions(data);
|
||||
|
||||
if (error) {
|
||||
errorMessage.value = errorMessageAsString(error, "Failed to load directories.");
|
||||
}
|
||||
|
||||
optionsLoading.value = false;
|
||||
}
|
||||
|
||||
function mapDataToOptions(data: any): Option[] {
|
||||
return data?.map((item: any) => {
|
||||
const option: Option = {
|
||||
name: item.text,
|
||||
fullPath: item.li_attr.full_path,
|
||||
value: item.li_attr.id,
|
||||
leaf: item.type === "file",
|
||||
disabled: item.state.disabled,
|
||||
options: item.children ? mapDataToOptions(item.children) : [],
|
||||
};
|
||||
|
||||
return option;
|
||||
});
|
||||
}
|
||||
|
||||
function getFullPathById(id: string): string {
|
||||
function traverse(nodes: Option[], targetId: string): string {
|
||||
for (const node of nodes) {
|
||||
if (node.value === targetId) {
|
||||
return node.fullPath as string;
|
||||
}
|
||||
if (node.options?.length > 0) {
|
||||
const result = traverse(node.options, targetId);
|
||||
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
return traverse(options.value, id);
|
||||
}
|
||||
|
||||
async function fetchExtAndDbKey() {
|
||||
extensionsList.value = datatypes.value;
|
||||
|
||||
extensionsList.value.sort((a, b) => (a.extension > b.extension ? 1 : a.extension < b.extension ? -1 : 0));
|
||||
|
||||
extensionsList.value = [autoExtension, ...extensionsList.value];
|
||||
|
||||
selectedExtension.value = autoExtension;
|
||||
|
||||
await dbKeyStore.fetchUploadDbKeys();
|
||||
|
||||
dbKeyList.value = dbKeyStore.uploadDbKeys as DbKeyList;
|
||||
|
||||
selectedDbKey.value = dbKeyStore.uploadDbKeys.find((item: DbKey) => item.id === "?");
|
||||
|
||||
dbKeyList.value.sort((a, b) => (a.id > b.id ? 1 : a.id < b.id ? -1 : 0));
|
||||
}
|
||||
|
||||
async function onImport() {
|
||||
if (pathMode.value) {
|
||||
const tmp: string[] = paths.value.split("\n");
|
||||
const validPaths: string[] = [];
|
||||
|
||||
for (let i = tmp.length - 1; i >= 0; i--) {
|
||||
var trimmed = tmp?.[i]?.trim();
|
||||
if (trimmed && trimmed?.length !== 0) {
|
||||
validPaths.push(trimmed);
|
||||
}
|
||||
}
|
||||
|
||||
if (validPaths.length === 0) {
|
||||
Toast.error("Please provide a valid path");
|
||||
return;
|
||||
} else {
|
||||
importFileOrFolder(validPaths, "admin_path");
|
||||
}
|
||||
} else {
|
||||
const source = `${props.target}_${filesMode.value ? "file" : "folder"}`;
|
||||
const validPaths: string[] = currentValue.value.map((item) => getFullPathById(item));
|
||||
|
||||
importFileOrFolder(validPaths, source);
|
||||
}
|
||||
}
|
||||
|
||||
async function importFileOrFolder(validPaths: string[], source: string) {
|
||||
const items: RequestData[] = [];
|
||||
|
||||
for (const path of validPaths) {
|
||||
const reqData: RequestData = {
|
||||
path: path,
|
||||
source: source,
|
||||
dbkey: selectedDbKey.value?.id || "?",
|
||||
encoded_folder_id: props.folderId,
|
||||
link_data: preserveOptions.value.includes("link_files"),
|
||||
space_to_tab: preserveOptions.value.includes("space_to_tab"),
|
||||
to_posix_lines: preserveOptions.value.includes("to_posix_lines"),
|
||||
tag_using_filenames: preserveOptions.value.includes("tags_from_filenames"),
|
||||
};
|
||||
|
||||
if (!pathMode.value) {
|
||||
reqData.file_type = selectedExtension.value.extension;
|
||||
}
|
||||
|
||||
if (!filesMode.value) {
|
||||
reqData.preserve_dirs = preserveOptions.value.includes("preserve_directory_structure");
|
||||
}
|
||||
|
||||
items.push(reqData);
|
||||
}
|
||||
|
||||
emit("onSelect", items);
|
||||
emit("onClose");
|
||||
}
|
||||
|
||||
watch(
|
||||
activeTab,
|
||||
() => {
|
||||
if (!pathMode.value) {
|
||||
fetchOptions();
|
||||
}
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
|
||||
function onSelectDbKey(item: DbKey) {
|
||||
selectedDbKey.value = item;
|
||||
}
|
||||
|
||||
function onSelectExtension(item: DetailedDatatypes) {
|
||||
selectedExtension.value = item;
|
||||
}
|
||||
|
||||
watch(
|
||||
() => datatypesLoading.value,
|
||||
() => {
|
||||
if (!datatypesLoading.value) {
|
||||
fetchExtAndDbKey();
|
||||
}
|
||||
}
|
||||
);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<BModal :title="title" visible scrollable content-class="directory-dataset-picker" @hide="emit('onClose')">
|
||||
<BTabs v-if="!pathMode" v-model="activeTab" fill pills>
|
||||
<BTab title="Choose Files" />
|
||||
|
||||
<BTab title="Choose Folders" />
|
||||
</BTabs>
|
||||
|
||||
<BAlert v-if="filesMode" show class="mt-2">
|
||||
All files you select will be imported into the current folder ignoring their folder structure.
|
||||
</BAlert>
|
||||
<BAlert v-else-if="!filesMode" show class="mt-2">
|
||||
All files within the selected folders and their sub-folders will be imported into the current folder.
|
||||
</BAlert>
|
||||
<BAlert v-else-if="pathMode" show class="mt-2">
|
||||
All files within the given folders and their sub-folders will be imported into the current folder.
|
||||
</BAlert>
|
||||
|
||||
<BFormCheckboxGroup v-model="preserveOptions" switches class="directory-dataset-picker-options">
|
||||
<BFormCheckbox value="link_files">Link files instead of copying </BFormCheckbox>
|
||||
<BFormCheckbox value="to_posix_lines">Convert line endings to POSIX</BFormCheckbox>
|
||||
<BFormCheckbox value="space_to_tab">Convert spaces to tabs</BFormCheckbox>
|
||||
<BFormCheckbox value="tags_from_filenames">Tag datasets based on file names</BFormCheckbox>
|
||||
<BFormCheckbox v-if="!filesMode || pathMode" value="preserve_directory_structure">
|
||||
Preserve directory structure
|
||||
</BFormCheckbox>
|
||||
</BFormCheckboxGroup>
|
||||
|
||||
<hr />
|
||||
|
||||
You can set database/build and extension type for all imported datasets at once:
|
||||
<BFormGroup label="Database/Build">
|
||||
<SingleItemSelector
|
||||
:current-item="selectedDbKey"
|
||||
collection-name="DB Keys"
|
||||
:items="dbKeyList"
|
||||
@update:selected-item="onSelectDbKey" />
|
||||
</BFormGroup>
|
||||
|
||||
<BFormGroup label="Extension">
|
||||
<SingleItemSelector
|
||||
:current-item="selectedExtension"
|
||||
collection-name="Extensions"
|
||||
:items="extensionsList"
|
||||
track-by="extension"
|
||||
label="extension"
|
||||
@update:selected-item="onSelectExtension" />
|
||||
</BFormGroup>
|
||||
|
||||
<hr />
|
||||
|
||||
<BFormTextarea
|
||||
v-if="pathMode"
|
||||
id="import_paths"
|
||||
v-model="paths"
|
||||
placeholder="Absolute paths (or paths relative to Galaxy root) separated by newline"
|
||||
rows="5" />
|
||||
<BAlert v-else-if="optionsLoading" variant="info" show>
|
||||
<LoadingSpan message="Loading directories" />
|
||||
</BAlert>
|
||||
<BAlert v-else-if="errorMessage" variant="danger" show>
|
||||
{{ errorMessage }}
|
||||
</BAlert>
|
||||
<FormDrilldown
|
||||
v-else
|
||||
:id="filesMode ? 'files' : 'folders'"
|
||||
v-model="currentValue"
|
||||
class="directory-dataset-picker-list"
|
||||
show-icons
|
||||
:options="options"
|
||||
multiple />
|
||||
|
||||
<template v-slot:modal-footer>
|
||||
<BButton size="sm" variant="secondary" :disabled="importing" @click="emit('onClose')">Close</BButton>
|
||||
<BButton size="sm" variant="primary" :disabled="importDisable" @click="onImport">
|
||||
{{ okButtonText }}
|
||||
</BButton>
|
||||
</template>
|
||||
</BModal>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.directory-dataset-picker {
|
||||
display: grid;
|
||||
grid-template-rows: max-content 1fr;
|
||||
|
||||
.directory-dataset-picker-options {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
}
|
||||
|
||||
.directory-dataset-picker-list {
|
||||
max-height: 100%;
|
||||
overflow-y: auto;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,7 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
import { library } from "@fortawesome/fontawesome-svg-core";
|
||||
import { faBook, faCaretDown, faDownload, faHome, faPlus, faTrash } from "@fortawesome/free-solid-svg-icons";
|
||||
import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome";
|
||||
import axios from "axios";
|
||||
import {
|
||||
BAlert,
|
||||
BButton,
|
||||
@@ -16,28 +16,23 @@ import { computed, reactive, ref } from "vue";
|
||||
|
||||
import { GalaxyApi } from "@/api";
|
||||
import { Services } from "@/components/Libraries/LibraryFolder/services";
|
||||
import mod_add_datasets from "@/components/Libraries/LibraryFolder/TopToolbar/add-datasets";
|
||||
import { deleteSelectedItems } from "@/components/Libraries/LibraryFolder/TopToolbar/delete-selected";
|
||||
import download from "@/components/Libraries/LibraryFolder/TopToolbar/download";
|
||||
import mod_import_collection from "@/components/Libraries/LibraryFolder/TopToolbar/import-to-history/import-collection";
|
||||
import mod_import_dataset from "@/components/Libraries/LibraryFolder/TopToolbar/import-to-history/import-dataset";
|
||||
import { type SelectionItem } from "@/components/SelectionDialog/selectionTypes";
|
||||
import { useConfig } from "@/composables/config";
|
||||
import { type DetailedDatatypes, useDetailedDatatypes } from "@/composables/datatypes";
|
||||
import { Toast } from "@/composables/toast";
|
||||
import { useDbKeyStore } from "@/stores/dbKeyStore";
|
||||
import { getAppRoot } from "@/onload";
|
||||
import { useUserStore } from "@/stores/userStore";
|
||||
|
||||
import FolderDetails from "@/components/Libraries/LibraryFolder/FolderDetails/FolderDetails.vue";
|
||||
import LibraryBreadcrumb from "@/components/Libraries/LibraryFolder/LibraryBreadcrumb.vue";
|
||||
import SearchField from "@/components/Libraries/LibraryFolder/SearchField.vue";
|
||||
import DirectoryDatasetPicker from "@/components/Libraries/LibraryFolder/TopToolbar/DirectoryDatasetPicker.vue";
|
||||
import ProgressBar from "@/components/ProgressBar.vue";
|
||||
import HistoryDatasetPicker from "@/components/SelectionDialog/HistoryDatasetPicker.vue";
|
||||
|
||||
library.add(faBook, faCaretDown, faDownload, faHome, faPlus, faTrash);
|
||||
|
||||
type GenomesList = { id: string; text: string }[];
|
||||
|
||||
interface Props {
|
||||
metadata: any;
|
||||
selected: any[];
|
||||
@@ -68,13 +63,8 @@ const { config, isConfigLoaded } = useConfig();
|
||||
const userStore = useUserStore();
|
||||
const { isAdmin } = storeToRefs(userStore);
|
||||
|
||||
const { datatypes } = useDetailedDatatypes();
|
||||
|
||||
const dbKeyStore = useDbKeyStore();
|
||||
|
||||
const modalShow = ref("");
|
||||
const genomesList = ref<GenomesList>([]);
|
||||
const extensionsList = ref<DetailedDatatypes[]>([]);
|
||||
type ImportSource = "history" | "userdir" | "importdir" | "path" | undefined;
|
||||
const modalShow = ref<ImportSource>();
|
||||
const progress = ref(false);
|
||||
const progressNote = ref("");
|
||||
const progressStatus = reactive({
|
||||
@@ -83,18 +73,6 @@ const progressStatus = reactive({
|
||||
errorCount: 0,
|
||||
runningCount: 0,
|
||||
});
|
||||
const auto = ref({
|
||||
id: "auto",
|
||||
extension: "auto",
|
||||
text: "Auto-detect",
|
||||
description: `This system will try to detect the file type automatically.
|
||||
If your file is not detected properly as one of the known formats,
|
||||
it most likely means that it has some format problems (e.g., different
|
||||
number of columns on different rows). You can still coerce the system
|
||||
to set your data to the format you think it should be.
|
||||
You can also upload compressed files, which will automatically be decompressed`,
|
||||
description_url: "",
|
||||
});
|
||||
|
||||
const services = new Services();
|
||||
|
||||
@@ -222,50 +200,10 @@ async function importToHistoryModal(isCollection: boolean) {
|
||||
}
|
||||
}
|
||||
|
||||
function onAddDatasets(source: string = "") {
|
||||
function onAddDatasets(source?: ImportSource) {
|
||||
modalShow.value = source;
|
||||
}
|
||||
|
||||
// TODO: after replacing the selection dialog with the new component that is not using jquery
|
||||
async function addDatasets(source: string) {
|
||||
await fetchExtAndGenomes();
|
||||
|
||||
new mod_add_datasets.AddDatasets({
|
||||
source: source,
|
||||
id: props.folderId,
|
||||
updateContent: updateContent,
|
||||
list_genomes: genomesList.value,
|
||||
list_extensions: extensionsList.value,
|
||||
});
|
||||
}
|
||||
|
||||
function updateContent() {
|
||||
emit("fetchFolderContents");
|
||||
}
|
||||
// END TODO
|
||||
|
||||
async function fetchExtAndGenomes() {
|
||||
try {
|
||||
extensionsList.value = datatypes.value;
|
||||
|
||||
extensionsList.value.sort((a, b) => (a.extension > b.extension ? 1 : a.extension < b.extension ? -1 : 0));
|
||||
|
||||
extensionsList.value = [auto.value, ...extensionsList.value];
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
|
||||
try {
|
||||
await dbKeyStore.fetchUploadDbKeys();
|
||||
|
||||
genomesList.value = dbKeyStore.uploadDbKeys;
|
||||
|
||||
genomesList.value.sort((a, b) => (a.id > b.id ? 1 : a.id < b.id ? -1 : 0));
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
}
|
||||
|
||||
function resetProgress() {
|
||||
progressStatus.total = 0;
|
||||
progressStatus.okCount = 0;
|
||||
@@ -273,7 +211,10 @@ function resetProgress() {
|
||||
progressStatus.runningCount = 0;
|
||||
}
|
||||
|
||||
async function onAddDatasetsFromHistory(selectedDatasets: SelectionItem[]) {
|
||||
async function addDatasets(
|
||||
selectedDatasets: SelectionItem[] | Record<string, string | boolean>[],
|
||||
datasetApiCall: Function
|
||||
) {
|
||||
resetProgress();
|
||||
|
||||
progress.value = true;
|
||||
@@ -286,22 +227,10 @@ async function onAddDatasetsFromHistory(selectedDatasets: SelectionItem[]) {
|
||||
try {
|
||||
progressStatus.runningCount++;
|
||||
|
||||
const { error } = await GalaxyApi().POST("/api/folders/{folder_id}/contents", {
|
||||
params: {
|
||||
path: { folder_id: props.folderId },
|
||||
},
|
||||
body: {
|
||||
ldda_message: null,
|
||||
from_hda_id: dataset.id,
|
||||
},
|
||||
});
|
||||
|
||||
if (error) {
|
||||
throw new Error(error.err_msg);
|
||||
}
|
||||
await datasetApiCall(dataset);
|
||||
|
||||
progressStatus.okCount++;
|
||||
} catch (err) {
|
||||
} catch (e) {
|
||||
progressStatus.errorCount++;
|
||||
} finally {
|
||||
progressStatus.runningCount--;
|
||||
@@ -323,6 +252,34 @@ async function onAddDatasetsFromHistory(selectedDatasets: SelectionItem[]) {
|
||||
emit("setBusy", false);
|
||||
emit("fetchFolderContents");
|
||||
}
|
||||
|
||||
function onAddDatasetsFromHistory(selectedDatasets: SelectionItem[]) {
|
||||
const datasetApiCall = async (dataset: SelectionItem) => {
|
||||
const { error } = await GalaxyApi().POST("/api/folders/{folder_id}/contents", {
|
||||
params: {
|
||||
path: { folder_id: props.folderId },
|
||||
},
|
||||
body: {
|
||||
ldda_message: null,
|
||||
from_hda_id: dataset.id,
|
||||
},
|
||||
});
|
||||
|
||||
if (error) {
|
||||
throw new Error(error.err_msg);
|
||||
}
|
||||
};
|
||||
|
||||
addDatasets(selectedDatasets, datasetApiCall);
|
||||
}
|
||||
|
||||
function onAddDatasetsDirectory(selectedDatasets: Record<string, string | boolean>[]) {
|
||||
const datasetApiCall = async (dataset: Record<string, string | boolean>) => {
|
||||
await axios.post(`${getAppRoot()}api/libraries/datasets`, dataset);
|
||||
};
|
||||
|
||||
addDatasets(selectedDatasets, datasetApiCall);
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -364,18 +321,18 @@ async function onAddDatasetsFromHistory(selectedDatasets: SelectionItem[]) {
|
||||
|
||||
<BDropdownItem @click="onAddDatasets('history')"> from History </BDropdownItem>
|
||||
|
||||
<BDropdownItem v-if="userLibraryImportDirAvailable" @click="addDatasets('userdir')">
|
||||
<BDropdownItem v-if="userLibraryImportDirAvailable" @click="onAddDatasets('userdir')">
|
||||
from User Directory
|
||||
</BDropdownItem>
|
||||
|
||||
<BDropdownDivider v-if="libraryImportDir || allowLibraryPathPaste" />
|
||||
|
||||
<BDropdownGroup v-if="libraryImportDir || allowLibraryPathPaste" header="Admins Only">
|
||||
<BDropdownItem v-if="libraryImportDir" @click="addDatasets('importdir')">
|
||||
<BDropdownItem v-if="libraryImportDir" @click="onAddDatasets('importdir')">
|
||||
from Import Directory
|
||||
</BDropdownItem>
|
||||
|
||||
<BDropdownItem v-if="allowLibraryPathPaste" @click="addDatasets('path')">
|
||||
<BDropdownItem v-if="allowLibraryPathPaste" @click="onAddDatasets('path')">
|
||||
from Path
|
||||
</BDropdownItem>
|
||||
</BDropdownGroup>
|
||||
@@ -449,5 +406,11 @@ async function onAddDatasetsFromHistory(selectedDatasets: SelectionItem[]) {
|
||||
:folder-id="props.folderId"
|
||||
@onSelect="onAddDatasetsFromHistory"
|
||||
@onClose="onAddDatasets" />
|
||||
<DirectoryDatasetPicker
|
||||
v-else-if="modalShow"
|
||||
:target="modalShow"
|
||||
:folder-id="props.folderId"
|
||||
@onSelect="onAddDatasetsDirectory"
|
||||
@onClose="onAddDatasets" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -1,579 +0,0 @@
|
||||
import "libs/jquery/jstree";
|
||||
|
||||
import { getGalaxyInstance } from "app";
|
||||
import Backbone from "backbone";
|
||||
import { Toast } from "composables/toast";
|
||||
import $ from "jquery";
|
||||
import { getAppRoot } from "onload/loadConfig";
|
||||
import _ from "underscore";
|
||||
import _l from "utils/localization";
|
||||
|
||||
import { updateProgress } from "./delete-selected";
|
||||
import mod_library_model from "./library-model";
|
||||
import mod_select from "./ui-select";
|
||||
|
||||
var AddDatasets = Backbone.View.extend({
|
||||
options: null,
|
||||
|
||||
initialize: function (options) {
|
||||
this.options = options;
|
||||
this.options.chain_call_control = {
|
||||
total_number: 0,
|
||||
failed_number: 0,
|
||||
};
|
||||
|
||||
this.list_extensions = options.list_extensions;
|
||||
this.list_genomes = options.list_genomes;
|
||||
this.showImportModal(options);
|
||||
},
|
||||
|
||||
/*
|
||||
Slightly adopted Backbone code
|
||||
*/
|
||||
showImportModal: function (options) {
|
||||
switch (options.source) {
|
||||
case "importdir":
|
||||
this.importFilesFromGalaxyFolderModal({
|
||||
source: "importdir",
|
||||
});
|
||||
break;
|
||||
case "path":
|
||||
this.importFilesFromPathModal();
|
||||
break;
|
||||
case "userdir":
|
||||
this.importFilesFromGalaxyFolderModal({
|
||||
source: "userdir",
|
||||
});
|
||||
break;
|
||||
default:
|
||||
// Galaxy.libraries.library_router.back();
|
||||
Toast.error("Invalid import source.");
|
||||
break;
|
||||
}
|
||||
},
|
||||
templateBrowserModal: function () {
|
||||
return _.template(
|
||||
`<div id="file_browser_modal">
|
||||
<div style="margin-bottom:1em;">
|
||||
<label title="Switch to selecting files" class="radio-inline import-type-switch">
|
||||
<input type="radio" name="jstree-radio" value="jstree-disable-folders" checked="checked">
|
||||
Choose Files
|
||||
</label>
|
||||
<label title="Switch to selecting folders" class="radio-inline import-type-switch">
|
||||
<input type="radio" name="jstree-radio" value="jstree-disable-files">
|
||||
Choose Folders
|
||||
</label>
|
||||
</div>
|
||||
<div class="alert alert-info jstree-files-message">
|
||||
All files you select will be imported into the current folder ignoring their folder structure.
|
||||
</div>
|
||||
<div class="alert alert-info jstree-folders-message" style="display:none;">
|
||||
All files within the selected folders and their subfolders will be imported into the current folder.
|
||||
</div>
|
||||
<div style="margin-bottom:1em;">
|
||||
<label class="checkbox-inline jstree-preserve-structure" style="display:none;">
|
||||
<input class="preserve-checkbox" type="checkbox" value="preserve_directory_structure">
|
||||
Preserve directory structure
|
||||
</label>
|
||||
<label class="checkbox-inline">
|
||||
<input class="link-checkbox" type="checkbox" value="link_files">
|
||||
Link files instead of copying
|
||||
</label>
|
||||
<label class="checkbox-inline">
|
||||
<input class="posix-checkbox" type="checkbox" value="to_posix_lines" checked="checked">
|
||||
Convert line endings to POSIX
|
||||
</label>
|
||||
<label class="checkbox-inline">
|
||||
<input class="spacetab-checkbox" type="checkbox" value="space_to_tab">
|
||||
Convert spaces to tabs
|
||||
</label>
|
||||
</div>
|
||||
<button title="Select all files" type="button" class="button primary-button libimport-select-all">
|
||||
Select all
|
||||
</button>
|
||||
<button title="Select no files" type="button" class="button primary-button libimport-select-none">
|
||||
Unselect all
|
||||
</button>
|
||||
<hr /> <!-- append jstree object here -->
|
||||
<div id="jstree_browser">
|
||||
</div>
|
||||
<hr />
|
||||
<p>You can set extension type and genome for all imported datasets at once:</p>
|
||||
<div>
|
||||
Type: <span id="library_extension_select" class="library-extension-select" />
|
||||
Genome: <span id="library_genome_select" class="library-genome-select" />
|
||||
</div>
|
||||
<br />
|
||||
<div>
|
||||
<label class="checkbox-inline tag-files">
|
||||
Tag datasets based on file names
|
||||
<input class="tag-files" type="checkbox" value="tag_using_filenames">
|
||||
</label>
|
||||
</div>
|
||||
</div>`
|
||||
);
|
||||
},
|
||||
templateImportPathModal: function () {
|
||||
return _.template(
|
||||
`<div id="file_browser_modal">
|
||||
<div class="alert alert-info jstree-folders-message">
|
||||
All files within the given folders and their subfolders will be imported into the current folder.
|
||||
</div>
|
||||
<div style="margin-bottom: 0.5em;">
|
||||
<label class="checkbox-inline">
|
||||
<input class="preserve-checkbox" type="checkbox" value="preserve_directory_structure">
|
||||
Preserve directory structure
|
||||
</label>
|
||||
<label class="checkbox-inline">
|
||||
<input class="link-checkbox" type="checkbox" value="link_files">
|
||||
Link files instead of copying
|
||||
</label>
|
||||
<br>
|
||||
<label class="checkbox-inline">
|
||||
<input class="posix-checkbox" type="checkbox" value="to_posix_lines" checked="checked">
|
||||
Convert line endings to POSIX
|
||||
</label>
|
||||
<label class="checkbox-inline">
|
||||
<input class="spacetab-checkbox" type="checkbox" value="space_to_tab">
|
||||
Convert spaces to tabs
|
||||
</label>
|
||||
</div>
|
||||
<textarea id="import_paths" class="form-control" rows="5"
|
||||
placeholder="Absolute paths (or paths relative to Galaxy root) separated by newline" autofocus>
|
||||
</textarea>
|
||||
<hr />
|
||||
<p>You can set extension type and genome for all imported datasets at once:</p>
|
||||
<div>
|
||||
Type: <span id="library_extension_select" class="library-extension-select"></span>
|
||||
Genome: <span id="library_genome_select" class="library-genome-select"></span>
|
||||
</div>
|
||||
<div>
|
||||
<label class="checkbox-inline tag-files">
|
||||
Tag datasets based on file names
|
||||
<input class="tag-files" type="checkbox" value="tag_using_filenames">
|
||||
</label>
|
||||
</div>
|
||||
</div>`
|
||||
);
|
||||
},
|
||||
renderSelectBoxes: function () {
|
||||
const Galaxy = getGalaxyInstance();
|
||||
// This won't work properly unlesss we already have the data fetched.
|
||||
// See this.fetchExtAndGenomes()
|
||||
this.select_genome = new mod_select.View({
|
||||
css: "library-genome-select",
|
||||
data: this.list_genomes,
|
||||
container: Galaxy.modal.$el.find("#library_genome_select"),
|
||||
value: "?",
|
||||
});
|
||||
this.select_extension = new mod_select.View({
|
||||
css: "library-extension-select",
|
||||
data: this.list_extensions,
|
||||
container: Galaxy.modal.$el.find("#library_extension_select"),
|
||||
value: "auto",
|
||||
});
|
||||
},
|
||||
/**
|
||||
* Create modal for importing from given directory
|
||||
* on Galaxy. Bind jQuery events.
|
||||
*/
|
||||
importFilesFromGalaxyFolderModal: function (options) {
|
||||
var template_modal = this.templateBrowserModal();
|
||||
const Galaxy = getGalaxyInstance();
|
||||
this.modal = Galaxy.modal;
|
||||
this.modal.show({
|
||||
closing_events: true,
|
||||
title: _l("Please select folders or files"),
|
||||
body: template_modal({}),
|
||||
buttons: {
|
||||
Import: () => {
|
||||
this.importFromJstreePath(this, options);
|
||||
},
|
||||
Close: () => {
|
||||
Galaxy.modal.hide();
|
||||
},
|
||||
},
|
||||
closing_callback: () => {
|
||||
// TODO update table without fetching new content from the server
|
||||
this.options.updateContent();
|
||||
// Galaxy.libraries.library_router.navigate(`folders/${this.id}`, {
|
||||
// trigger: true,
|
||||
// });
|
||||
},
|
||||
});
|
||||
|
||||
$(".libimport-select-all").bind("click", () => {
|
||||
$("#jstree_browser").jstree("check_all");
|
||||
});
|
||||
$(".libimport-select-none").bind("click", () => {
|
||||
$("#jstree_browser").jstree("uncheck_all");
|
||||
});
|
||||
|
||||
this.renderSelectBoxes();
|
||||
options.disabled_jstree_element = "folders";
|
||||
this.renderJstree(options);
|
||||
|
||||
$("input[type=radio]").change((event) => {
|
||||
if (event.target.value === "jstree-disable-folders") {
|
||||
options.disabled_jstree_element = "folders";
|
||||
this.renderJstree(options);
|
||||
$(".jstree-folders-message").hide();
|
||||
$(".jstree-preserve-structure").hide();
|
||||
$(".jstree-files-message").show();
|
||||
} else if (event.target.value === "jstree-disable-files") {
|
||||
$(".jstree-files-message").hide();
|
||||
$(".jstree-folders-message").show();
|
||||
$(".jstree-preserve-structure").show();
|
||||
options.disabled_jstree_element = "files";
|
||||
this.renderJstree(options);
|
||||
}
|
||||
});
|
||||
},
|
||||
/**
|
||||
* Take the selected items from the jstree, create a request queue
|
||||
* and send them one by one to the server for importing into
|
||||
* the current folder.
|
||||
*
|
||||
* jstree.js has to be loaded before
|
||||
* @see renderJstree
|
||||
*/
|
||||
importFromJstreePath: function (that, options) {
|
||||
var all_nodes = $("#jstree_browser").jstree().get_selected(true);
|
||||
// remove the disabled elements that could have been trigerred with the 'select all'
|
||||
var selected_nodes = _.filter(all_nodes, (node) => node.state.disabled == false);
|
||||
var preserve_dirs = this.modal.$el.find(".preserve-checkbox").is(":checked");
|
||||
var link_data = this.modal.$el.find(".link-checkbox").is(":checked");
|
||||
var space_to_tab = this.modal.$el.find(".spacetab-checkbox").is(":checked");
|
||||
var to_posix_lines = this.modal.$el.find(".posix-checkbox").is(":checked");
|
||||
var file_type = this.select_extension.value();
|
||||
var dbkey = this.select_genome.value();
|
||||
var tag_using_filenames = this.modal.$el.find(".tag-files").is(":checked");
|
||||
var selection_type = selected_nodes[0].type;
|
||||
var paths = [];
|
||||
if (selected_nodes.length < 1) {
|
||||
Toast.info("Please select some items first.");
|
||||
} else {
|
||||
this.modal.disableButton("Import");
|
||||
for (let i = selected_nodes.length - 1; i >= 0; i--) {
|
||||
if (selected_nodes[i].li_attr.full_path !== undefined) {
|
||||
// should be always String
|
||||
paths.push(`"${selected_nodes[i].li_attr.full_path}"`);
|
||||
}
|
||||
}
|
||||
this.initChainCallControlAddingDatasets({
|
||||
length: paths.length,
|
||||
});
|
||||
if (selection_type === "folder") {
|
||||
const full_source = `${options.source}_folder`;
|
||||
this.chainCallImportingFolders({
|
||||
paths: paths,
|
||||
preserve_dirs: preserve_dirs,
|
||||
link_data: link_data,
|
||||
space_to_tab: space_to_tab,
|
||||
to_posix_lines: to_posix_lines,
|
||||
source: full_source,
|
||||
file_type: file_type,
|
||||
dbkey: dbkey,
|
||||
tag_using_filenames: tag_using_filenames,
|
||||
});
|
||||
} else if (selection_type === "file") {
|
||||
const full_source = `${options.source}_file`;
|
||||
this.chainCallImportingUserdirFiles({
|
||||
paths: paths,
|
||||
file_type: file_type,
|
||||
dbkey: dbkey,
|
||||
link_data: link_data,
|
||||
space_to_tab: space_to_tab,
|
||||
to_posix_lines: to_posix_lines,
|
||||
source: full_source,
|
||||
tag_using_filenames: tag_using_filenames,
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Take the array of paths and create a request for each of them
|
||||
* calling them in chain. Update the progress bar in between each.
|
||||
* @param {array} paths paths relative to user folder on Galaxy
|
||||
* @param {boolean} tag_using_filenames add tags to datasets using names of files
|
||||
*/
|
||||
chainCallImportingUserdirFiles: function (options) {
|
||||
const Galaxy = getGalaxyInstance();
|
||||
const popped_item = options.paths.pop();
|
||||
if (typeof popped_item === "undefined") {
|
||||
if (this.options.chain_call_control.failed_number === 0) {
|
||||
Toast.success("Selected files imported into the current folder");
|
||||
Galaxy.modal.hide();
|
||||
} else {
|
||||
Toast.error("An error occurred.");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
const post_url = `${getAppRoot()}api/libraries/datasets`;
|
||||
const post_data = {
|
||||
encoded_folder_id: this.id,
|
||||
source: options.source,
|
||||
path: popped_item,
|
||||
file_type: options.file_type,
|
||||
link_data: options.link_data,
|
||||
space_to_tab: options.space_to_tab,
|
||||
to_posix_lines: options.to_posix_lines,
|
||||
dbkey: options.dbkey,
|
||||
tag_using_filenames: options.tag_using_filenames,
|
||||
};
|
||||
const promise = $.when($.post(post_url, post_data));
|
||||
promise
|
||||
.done((response) => {
|
||||
updateProgress();
|
||||
this.chainCallImportingUserdirFiles(options);
|
||||
})
|
||||
.fail(() => {
|
||||
this.options.chain_call_control.failed_number += 1;
|
||||
updateProgress();
|
||||
this.chainCallImportingUserdirFiles(options);
|
||||
});
|
||||
},
|
||||
/**
|
||||
* Fetch the contents of user directory on Galaxy
|
||||
* and render jstree component based on received
|
||||
* data.
|
||||
* @param {[type]} options [description]
|
||||
*/
|
||||
renderJstree: function (options) {
|
||||
this.options = _.extend(this.options, options);
|
||||
var target = options.source || "userdir";
|
||||
var disabled_jstree_element = this.options.disabled_jstree_element;
|
||||
this.jstree = new mod_library_model.Jstree();
|
||||
this.jstree.url = `${this.jstree.urlRoot}?target=${target}&format=jstree&disable=${disabled_jstree_element}`;
|
||||
this.jstree.fetch({
|
||||
success: (model, response) => {
|
||||
$("#jstree_browser").jstree("destroy");
|
||||
$("#jstree_browser").jstree({
|
||||
core: {
|
||||
data: model,
|
||||
},
|
||||
plugins: ["types", "checkbox"],
|
||||
types: {
|
||||
folder: {
|
||||
icon: "jstree-folder",
|
||||
},
|
||||
file: {
|
||||
icon: "jstree-file",
|
||||
},
|
||||
},
|
||||
checkbox: {
|
||||
three_state: false,
|
||||
},
|
||||
});
|
||||
},
|
||||
error: (model, response) => {
|
||||
if (typeof response.responseJSON !== "undefined") {
|
||||
if (response.responseJSON.err_code === 404001) {
|
||||
Toast.warning(response.responseJSON.err_msg);
|
||||
getGalaxyInstance().modal.hide();
|
||||
} else {
|
||||
Toast.error(response.responseJSON.err_msg);
|
||||
}
|
||||
} else {
|
||||
Toast.error("An error occurred.");
|
||||
}
|
||||
},
|
||||
});
|
||||
},
|
||||
/**
|
||||
* Create modal for importing from Galaxy path.
|
||||
*/
|
||||
importFilesFromPathModal: function () {
|
||||
const Galaxy = getGalaxyInstance();
|
||||
this.modal = Galaxy.modal;
|
||||
var template_modal = this.templateImportPathModal();
|
||||
this.modal.show({
|
||||
closing_events: true,
|
||||
title: _l("Please enter paths to import"),
|
||||
body: template_modal({}),
|
||||
buttons: {
|
||||
Import: () => {
|
||||
this.importFromPathsClicked(this);
|
||||
},
|
||||
Close: () => {
|
||||
Galaxy.modal.hide();
|
||||
},
|
||||
},
|
||||
closing_callback: () => {
|
||||
// TODO update table without fetching new content from the server
|
||||
this.options.updateContent();
|
||||
|
||||
// Galaxy.libraries.library_router.navigate(`folders/${this.id}`, {
|
||||
// trigger: true,
|
||||
// });
|
||||
},
|
||||
});
|
||||
this.renderSelectBoxes();
|
||||
},
|
||||
/**
|
||||
* Take the paths from the textarea, split it, create
|
||||
* a request queue and call a function that starts sending
|
||||
* one by one to be imported on the server.
|
||||
*/
|
||||
importFromPathsClicked: function () {
|
||||
var preserve_dirs = this.modal.$el.find(".preserve-checkbox").is(":checked");
|
||||
var link_data = this.modal.$el.find(".link-checkbox").is(":checked");
|
||||
var space_to_tab = this.modal.$el.find(".spacetab-checkbox").is(":checked");
|
||||
var to_posix_lines = this.modal.$el.find(".posix-checkbox").is(":checked");
|
||||
var tag_using_filenames = this.modal.$el.find(".tag-files").is(":checked");
|
||||
var file_type = this.select_extension.value();
|
||||
var dbkey = this.select_genome.value();
|
||||
var paths = $("textarea#import_paths").val();
|
||||
var valid_paths = [];
|
||||
if (!paths) {
|
||||
Toast.info("Please enter a path relative to Galaxy root.");
|
||||
} else {
|
||||
this.modal.disableButton("Import");
|
||||
paths = paths.split("\n");
|
||||
for (let i = paths.length - 1; i >= 0; i--) {
|
||||
var trimmed = paths[i].trim();
|
||||
if (trimmed.length !== 0) {
|
||||
valid_paths.push(trimmed);
|
||||
}
|
||||
}
|
||||
this.initChainCallControlAddingDatasets({
|
||||
length: valid_paths.length,
|
||||
});
|
||||
this.chainCallImportingFolders({
|
||||
paths: valid_paths,
|
||||
preserve_dirs: preserve_dirs,
|
||||
link_data: link_data,
|
||||
space_to_tab: space_to_tab,
|
||||
to_posix_lines: to_posix_lines,
|
||||
source: "admin_path",
|
||||
file_type: file_type,
|
||||
tag_using_filenames: tag_using_filenames,
|
||||
dbkey: dbkey,
|
||||
});
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Take the array of paths and create a request for each of them
|
||||
* calling them in series. Update the progress bar in between each.
|
||||
* @param {array} paths paths relative to Galaxy root folder
|
||||
* @param {boolean} preserve_dirs indicates whether to preserve folder structure
|
||||
* @param {boolean} link_data copy files to Galaxy or link instead
|
||||
* @param {boolean} to_posix_lines convert line endings to POSIX standard
|
||||
* @param {boolean} space_to_tab convert spaces to tabs
|
||||
* @param {str} source string representing what type of folder
|
||||
* is the source of import
|
||||
* @param {boolean} tag_using_filenames add tags to datasets using names of files
|
||||
*/
|
||||
chainCallImportingFolders: function (options) {
|
||||
const Galaxy = getGalaxyInstance();
|
||||
// TODO need to check which paths to call
|
||||
const popped_item = options.paths.pop();
|
||||
if (typeof popped_item == "undefined") {
|
||||
if (this.options.chain_call_control.failed_number === 0) {
|
||||
Toast.success("Selected folders and their contents imported into the current folder.");
|
||||
Galaxy.modal.hide();
|
||||
} else {
|
||||
// TODO better error report
|
||||
Toast.error("An error occurred.");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
const post_url = `${getAppRoot()}api/libraries/datasets`;
|
||||
const post_data = {
|
||||
encoded_folder_id: this.id,
|
||||
source: options.source,
|
||||
path: popped_item,
|
||||
preserve_dirs: options.preserve_dirs,
|
||||
link_data: options.link_data,
|
||||
to_posix_lines: options.to_posix_lines,
|
||||
space_to_tab: options.space_to_tab,
|
||||
file_type: options.file_type,
|
||||
dbkey: options.dbkey,
|
||||
tag_using_filenames: options.tag_using_filenames,
|
||||
};
|
||||
const promise = $.when($.post(post_url, post_data));
|
||||
promise
|
||||
.done((response) => {
|
||||
updateProgress();
|
||||
this.chainCallImportingFolders(options);
|
||||
})
|
||||
.fail(() => {
|
||||
this.options.chain_call_control.failed_number += 1;
|
||||
updateProgress();
|
||||
this.chainCallImportingFolders(options);
|
||||
});
|
||||
},
|
||||
templateAddingDatasetsProgressBar: function () {
|
||||
return _.template(
|
||||
`<div class="import_text">
|
||||
Adding selected datasets to library folder <b><%= _.escape(folder_name) %></b>
|
||||
</div>
|
||||
<div class="progress">
|
||||
<div class="progress-bar progress-bar-import" role="progressbar" aria-valuenow="0" aria-valuemin="0"
|
||||
aria-valuemax="100" style="width: 00%;">
|
||||
<span class="completion_span">0% Complete</span>
|
||||
</div>
|
||||
</div>`
|
||||
);
|
||||
},
|
||||
initChainCallControlAddingDatasets: function (options) {
|
||||
var template;
|
||||
template = this.templateAddingDatasetsProgressBar();
|
||||
this.modal.$el.find(".modal-body").html(
|
||||
template({
|
||||
folder_name: this.options.folder_name,
|
||||
})
|
||||
);
|
||||
|
||||
// var progress_bar_tmpl = this.templateAddingDatasetsProgressBar();
|
||||
// this.modal.$el.find( '.modal-body' ).html( progress_bar_tmpl( { folder_name : this.options.folder_name } ) );
|
||||
this.progress = 0;
|
||||
this.progressStep = 100 / options.length;
|
||||
this.options.chain_call_control.total_number = options.length;
|
||||
this.options.chain_call_control.failed_number = 0;
|
||||
},
|
||||
|
||||
/**
|
||||
* Take the array of hdas and create a request for each.
|
||||
* Call them in chain and update progress bar in between each.
|
||||
* @param {array} hdas_set array of empty hda objects
|
||||
*/
|
||||
chainCallAddingHdas: function (hdas_set) {
|
||||
const Galaxy = getGalaxyInstance();
|
||||
this.added_hdas = new mod_library_model.Folder();
|
||||
var popped_item = hdas_set.pop();
|
||||
if (typeof popped_item == "undefined") {
|
||||
if (this.options.chain_call_control.failed_number === 0) {
|
||||
Toast.success("Selected datasets from history added to the folder");
|
||||
} else if (this.options.chain_call_control.failed_number === this.options.chain_call_control.total_number) {
|
||||
Toast.error("There was an error and no datasets were added to the folder.");
|
||||
} else if (this.options.chain_call_control.failed_number < this.options.chain_call_control.total_number) {
|
||||
Toast.warning("Some of the datasets could not be added to the folder");
|
||||
}
|
||||
this.options.updateContent();
|
||||
Galaxy.modal.hide();
|
||||
return this.added_hdas;
|
||||
}
|
||||
var promise = $.when(
|
||||
popped_item.save({
|
||||
from_hda_id: popped_item.get("from_hda_id"),
|
||||
})
|
||||
);
|
||||
|
||||
promise
|
||||
.done((model) => {
|
||||
// TODO add to lib
|
||||
// Galaxy.libraries.folderListView.collection.add(model);
|
||||
updateProgress();
|
||||
this.chainCallAddingHdas(hdas_set);
|
||||
})
|
||||
.fail(() => {
|
||||
this.options.chain_call_control.failed_number += 1;
|
||||
updateProgress();
|
||||
this.chainCallAddingHdas(hdas_set);
|
||||
});
|
||||
},
|
||||
});
|
||||
export default {
|
||||
AddDatasets: AddDatasets,
|
||||
};
|
||||
@@ -5,8 +5,8 @@
|
||||
v-if="items"
|
||||
v-model="selectedItem"
|
||||
:deselect-label="null"
|
||||
track-by="id"
|
||||
label="text"
|
||||
:track-by="trackBy"
|
||||
:label="label"
|
||||
:options="items"
|
||||
:searchable="true"
|
||||
:allow-empty="false"
|
||||
@@ -54,9 +54,17 @@ export default {
|
||||
default: null,
|
||||
},
|
||||
/** The initially selected item. */
|
||||
currentItemId: {
|
||||
currentItem: {
|
||||
type: Object,
|
||||
default: null,
|
||||
},
|
||||
label: {
|
||||
type: String,
|
||||
required: true,
|
||||
default: "text",
|
||||
},
|
||||
trackBy: {
|
||||
type: String,
|
||||
default: "id",
|
||||
},
|
||||
},
|
||||
data() {
|
||||
@@ -72,7 +80,7 @@ export default {
|
||||
},
|
||||
watch: {
|
||||
items: function () {
|
||||
this.selectedItem = this.items.find((item) => item.id == this.currentItemId);
|
||||
this.selectedItem = this.currentItem;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
|
||||
@@ -31,7 +31,6 @@ $fa-font-path: "../../../node_modules/@fortawesome/fontawesome-free/webfonts/";
|
||||
@import "library.scss";
|
||||
@import "trackster.scss";
|
||||
@import "toastr.scss";
|
||||
@import "jstree.scss";
|
||||
@import "tour.scss";
|
||||
@import "flex.scss";
|
||||
@import "charts.scss";
|
||||
|
||||
@@ -1,990 +0,0 @@
|
||||
/* jsTree default theme */
|
||||
.jstree-node,
|
||||
.jstree-children,
|
||||
.jstree-container-ul {
|
||||
display: block;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style-type: none;
|
||||
list-style-image: none;
|
||||
}
|
||||
.jstree-node {
|
||||
white-space: nowrap;
|
||||
}
|
||||
.jstree-anchor {
|
||||
display: inline-block;
|
||||
color: black;
|
||||
white-space: nowrap;
|
||||
padding: 0 4px 0 1px;
|
||||
margin: 0;
|
||||
vertical-align: top;
|
||||
}
|
||||
.jstree-anchor:focus {
|
||||
outline: 0;
|
||||
}
|
||||
.jstree-anchor,
|
||||
.jstree-anchor:link,
|
||||
.jstree-anchor:visited,
|
||||
.jstree-anchor:hover,
|
||||
.jstree-anchor:active {
|
||||
text-decoration: none;
|
||||
color: inherit;
|
||||
}
|
||||
.jstree-icon {
|
||||
display: inline-block;
|
||||
text-decoration: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
vertical-align: top;
|
||||
text-align: center;
|
||||
}
|
||||
.jstree-icon:empty {
|
||||
display: inline-block;
|
||||
text-decoration: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
vertical-align: top;
|
||||
text-align: center;
|
||||
}
|
||||
.jstree-ocl {
|
||||
cursor: pointer;
|
||||
}
|
||||
.jstree-leaf > .jstree-ocl {
|
||||
cursor: default;
|
||||
}
|
||||
.jstree .jstree-open > .jstree-children {
|
||||
display: block;
|
||||
}
|
||||
.jstree .jstree-closed > .jstree-children,
|
||||
.jstree .jstree-leaf > .jstree-children {
|
||||
display: none;
|
||||
}
|
||||
.jstree-anchor > .jstree-themeicon {
|
||||
margin-right: 2px;
|
||||
}
|
||||
.jstree-no-icons .jstree-themeicon,
|
||||
.jstree-anchor > .jstree-themeicon-hidden {
|
||||
display: none;
|
||||
}
|
||||
.jstree-rtl .jstree-anchor {
|
||||
padding: 0 1px 0 4px;
|
||||
}
|
||||
.jstree-rtl .jstree-anchor > .jstree-themeicon {
|
||||
margin-left: 2px;
|
||||
margin-right: 0;
|
||||
}
|
||||
.jstree-rtl .jstree-node {
|
||||
margin-left: 0;
|
||||
}
|
||||
.jstree-rtl .jstree-container-ul > .jstree-node {
|
||||
margin-right: 0;
|
||||
}
|
||||
.jstree-wholerow-ul {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
min-width: 100%;
|
||||
}
|
||||
.jstree-wholerow-ul .jstree-leaf > .jstree-ocl {
|
||||
cursor: pointer;
|
||||
}
|
||||
.jstree-wholerow-ul .jstree-anchor,
|
||||
.jstree-wholerow-ul .jstree-icon {
|
||||
position: relative;
|
||||
}
|
||||
.jstree-wholerow-ul .jstree-wholerow {
|
||||
width: 100%;
|
||||
cursor: pointer;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
.vakata-context {
|
||||
display: none;
|
||||
}
|
||||
.vakata-context,
|
||||
.vakata-context ul {
|
||||
margin: 0;
|
||||
padding: 2px;
|
||||
position: absolute;
|
||||
background: #f5f5f5;
|
||||
border: 1px solid #979797;
|
||||
-moz-box-shadow: 5px 5px 4px -4px #666666;
|
||||
-webkit-box-shadow: 2px 2px 2px #999999;
|
||||
box-shadow: 2px 2px 2px #999999;
|
||||
}
|
||||
.vakata-context ul {
|
||||
list-style: none;
|
||||
left: 100%;
|
||||
margin-top: -2.7em;
|
||||
margin-left: -4px;
|
||||
}
|
||||
.vakata-context .vakata-context-right ul {
|
||||
left: auto;
|
||||
right: 100%;
|
||||
margin-left: auto;
|
||||
margin-right: -4px;
|
||||
}
|
||||
.vakata-context li {
|
||||
list-style: none;
|
||||
display: inline;
|
||||
}
|
||||
.vakata-context li > a {
|
||||
display: block;
|
||||
padding: 0 2em 0 2em;
|
||||
text-decoration: none;
|
||||
width: auto;
|
||||
color: black;
|
||||
white-space: nowrap;
|
||||
line-height: 2.4em;
|
||||
-moz-text-shadow: 1px 1px 0 white;
|
||||
-webkit-text-shadow: 1px 1px 0 white;
|
||||
text-shadow: 1px 1px 0 white;
|
||||
-moz-border-radius: 1px;
|
||||
-webkit-border-radius: 1px;
|
||||
border-radius: 1px;
|
||||
}
|
||||
.vakata-context li > a:hover {
|
||||
position: relative;
|
||||
background-color: #e8eff7;
|
||||
-moz-box-shadow: 0 0 2px #0a6aa1;
|
||||
-webkit-box-shadow: 0 0 2px #0a6aa1;
|
||||
box-shadow: 0 0 2px #0a6aa1;
|
||||
}
|
||||
.vakata-context li > a.vakata-context-parent {
|
||||
background-image: url("data:image/gif;base64,R0lGODlhCwAHAIAAACgoKP///yH5BAEAAAEALAAAAAALAAcAAAIORI4JlrqN1oMSnmmZDQUAOw==");
|
||||
background-position: right center;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
.vakata-context li > a:focus {
|
||||
outline: 0;
|
||||
}
|
||||
.vakata-context .vakata-context-hover > a {
|
||||
position: relative;
|
||||
background-color: #e8eff7;
|
||||
-moz-box-shadow: 0 0 2px #0a6aa1;
|
||||
-webkit-box-shadow: 0 0 2px #0a6aa1;
|
||||
box-shadow: 0 0 2px #0a6aa1;
|
||||
}
|
||||
.vakata-context .vakata-context-separator > a,
|
||||
.vakata-context .vakata-context-separator > a:hover {
|
||||
background: white;
|
||||
border: 0;
|
||||
border-top: 1px solid #e2e3e3;
|
||||
height: 1px;
|
||||
min-height: 1px;
|
||||
max-height: 1px;
|
||||
padding: 0;
|
||||
margin: 0 0 0 2.4em;
|
||||
border-left: 1px solid #e0e0e0;
|
||||
-moz-text-shadow: 0 0 0 transparent;
|
||||
-webkit-text-shadow: 0 0 0 transparent;
|
||||
text-shadow: 0 0 0 transparent;
|
||||
-moz-box-shadow: 0 0 0 transparent;
|
||||
-webkit-box-shadow: 0 0 0 transparent;
|
||||
box-shadow: 0 0 0 transparent;
|
||||
-moz-border-radius: 0;
|
||||
-webkit-border-radius: 0;
|
||||
border-radius: 0;
|
||||
}
|
||||
.vakata-context .vakata-contextmenu-disabled a,
|
||||
.vakata-context .vakata-contextmenu-disabled a:hover {
|
||||
color: silver;
|
||||
background-color: transparent;
|
||||
border: 0;
|
||||
box-shadow: 0 0 0;
|
||||
}
|
||||
.vakata-context li > a > i {
|
||||
text-decoration: none;
|
||||
display: inline-block;
|
||||
width: 2.4em;
|
||||
height: 2.4em;
|
||||
background: transparent;
|
||||
margin: 0 0 0 -2em;
|
||||
vertical-align: top;
|
||||
text-align: center;
|
||||
line-height: 2.4em;
|
||||
}
|
||||
.vakata-context li > a > i:empty {
|
||||
width: 2.4em;
|
||||
line-height: 2.4em;
|
||||
}
|
||||
.vakata-context li > a .vakata-contextmenu-sep {
|
||||
display: inline-block;
|
||||
width: 1px;
|
||||
height: 2.4em;
|
||||
background: white;
|
||||
margin: 0 0.5em 0 0;
|
||||
border-left: 1px solid #e2e3e3;
|
||||
}
|
||||
.vakata-context .vakata-contextmenu-shortcut {
|
||||
font-size: 0.8em;
|
||||
color: silver;
|
||||
opacity: 0.5;
|
||||
display: none;
|
||||
}
|
||||
.vakata-context-rtl ul {
|
||||
left: auto;
|
||||
right: 100%;
|
||||
margin-left: auto;
|
||||
margin-right: -4px;
|
||||
}
|
||||
.vakata-context-rtl li > a.vakata-context-parent {
|
||||
background-image: url("data:image/gif;base64,R0lGODlhCwAHAIAAACgoKP///yH5BAEAAAEALAAAAAALAAcAAAINjI+AC7rWHIsPtmoxLAA7");
|
||||
background-position: left center;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
.vakata-context-rtl .vakata-context-separator > a {
|
||||
margin: 0 2.4em 0 0;
|
||||
border-left: 0;
|
||||
border-right: 1px solid #e2e3e3;
|
||||
}
|
||||
.vakata-context-rtl .vakata-context-left ul {
|
||||
right: auto;
|
||||
left: 100%;
|
||||
margin-left: -4px;
|
||||
margin-right: auto;
|
||||
}
|
||||
.vakata-context-rtl li > a > i {
|
||||
margin: 0 -2em 0 0;
|
||||
}
|
||||
.vakata-context-rtl li > a .vakata-contextmenu-sep {
|
||||
margin: 0 0 0 0.5em;
|
||||
border-left-color: white;
|
||||
background: #e2e3e3;
|
||||
}
|
||||
#jstree-marker {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
margin: -5px 0 0 0;
|
||||
padding: 0;
|
||||
border-right: 0;
|
||||
border-top: 5px solid transparent;
|
||||
border-bottom: 5px solid transparent;
|
||||
border-left: 5px solid;
|
||||
width: 0;
|
||||
height: 0;
|
||||
font-size: 0;
|
||||
line-height: 0;
|
||||
}
|
||||
#jstree-dnd {
|
||||
line-height: 16px;
|
||||
margin: 0;
|
||||
padding: 4px;
|
||||
}
|
||||
#jstree-dnd .jstree-icon,
|
||||
#jstree-dnd .jstree-copy {
|
||||
display: inline-block;
|
||||
text-decoration: none;
|
||||
margin: 0 2px 0 0;
|
||||
padding: 0;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
#jstree-dnd .jstree-ok {
|
||||
background: green;
|
||||
}
|
||||
#jstree-dnd .jstree-er {
|
||||
background: red;
|
||||
}
|
||||
#jstree-dnd .jstree-copy {
|
||||
margin: 0 2px 0 2px;
|
||||
}
|
||||
.jstree-default .jstree-node,
|
||||
.jstree-default .jstree-icon {
|
||||
background-repeat: no-repeat;
|
||||
background-color: transparent;
|
||||
}
|
||||
.jstree-default .jstree-anchor,
|
||||
.jstree-default .jstree-wholerow {
|
||||
transition: background-color 0.15s, box-shadow 0.15s;
|
||||
}
|
||||
.jstree-default .jstree-hovered {
|
||||
background: #e7f4f9;
|
||||
border-radius: 2px;
|
||||
box-shadow: inset 0 0 1px #ccc;
|
||||
}
|
||||
.jstree-default .jstree-clicked {
|
||||
background: #beebff;
|
||||
border-radius: 2px;
|
||||
box-shadow: inset 0 0 1px #999;
|
||||
}
|
||||
.jstree-default .jstree-no-icons .jstree-anchor > .jstree-themeicon {
|
||||
display: none;
|
||||
}
|
||||
.jstree-default .jstree-disabled {
|
||||
background: transparent;
|
||||
color: #666;
|
||||
}
|
||||
.jstree-default .jstree-disabled.jstree-hovered {
|
||||
background: transparent;
|
||||
box-shadow: none;
|
||||
}
|
||||
.jstree-default .jstree-disabled.jstree-clicked {
|
||||
background: #efefef;
|
||||
}
|
||||
.jstree-default .jstree-disabled > .jstree-icon {
|
||||
opacity: 0.8;
|
||||
filter: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg'><filter id='jstree-grayscale'><feColorMatrix type='matrix' values='0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0 0 0 1 0'/></filter></svg>#jstree-grayscale");
|
||||
/* Firefox 10+ */
|
||||
filter: gray;
|
||||
/* IE6-9 */
|
||||
-webkit-filter: grayscale(100%);
|
||||
/* Chrome 19+ & Safari 6+ */
|
||||
}
|
||||
.jstree-default .jstree-search {
|
||||
font-style: italic;
|
||||
color: #8b0000;
|
||||
font-weight: bold;
|
||||
}
|
||||
.jstree-default .jstree-no-checkboxes .jstree-checkbox {
|
||||
display: none !important;
|
||||
}
|
||||
.jstree-default.jstree-checkbox-no-clicked .jstree-clicked {
|
||||
background: transparent;
|
||||
box-shadow: none;
|
||||
}
|
||||
.jstree-default.jstree-checkbox-no-clicked .jstree-clicked.jstree-hovered {
|
||||
background: #e7f4f9;
|
||||
}
|
||||
.jstree-default.jstree-checkbox-no-clicked > .jstree-wholerow-ul .jstree-wholerow-clicked {
|
||||
background: transparent;
|
||||
}
|
||||
.jstree-default.jstree-checkbox-no-clicked > .jstree-wholerow-ul .jstree-wholerow-clicked.jstree-wholerow-hovered {
|
||||
background: #e7f4f9;
|
||||
}
|
||||
#jstree-dnd.jstree-default .jstree-ok,
|
||||
#jstree-dnd.jstree-default .jstree-er {
|
||||
background-image: url("../../assets/images/jstree/32px.png");
|
||||
background-repeat: no-repeat;
|
||||
background-color: transparent;
|
||||
}
|
||||
#jstree-dnd.jstree-default i {
|
||||
background: transparent;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
#jstree-dnd.jstree-default .jstree-ok {
|
||||
background-position: -9px -71px;
|
||||
}
|
||||
#jstree-dnd.jstree-default .jstree-er {
|
||||
background-position: -39px -71px;
|
||||
}
|
||||
.jstree-default > .jstree-striped {
|
||||
background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAkCAMAAAB/qqA+AAAABlBMVEUAAAAAAAClZ7nPAAAAAnRSTlMNAMM9s3UAAAAXSURBVHjajcEBAQAAAIKg/H/aCQZ70AUBjAATb6YPDgAAAABJRU5ErkJggg==")
|
||||
left top repeat;
|
||||
}
|
||||
.jstree-default > .jstree-wholerow-ul .jstree-hovered,
|
||||
.jstree-default > .jstree-wholerow-ul .jstree-clicked {
|
||||
background: transparent;
|
||||
box-shadow: none;
|
||||
border-radius: 0;
|
||||
}
|
||||
.jstree-default .jstree-wholerow {
|
||||
-moz-box-sizing: border-box;
|
||||
-webkit-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.jstree-default .jstree-wholerow-hovered {
|
||||
background: #e7f4f9;
|
||||
}
|
||||
.jstree-default .jstree-wholerow-clicked {
|
||||
background: #beebff;
|
||||
background: -moz-linear-gradient(top, #beebff 0%, #a8e4ff 100%);
|
||||
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #beebff), color-stop(100%, #a8e4ff));
|
||||
background: -webkit-linear-gradient(top, #beebff 0%, #a8e4ff 100%);
|
||||
background: -o-linear-gradient(top, #beebff 0%, #a8e4ff 100%);
|
||||
background: -ms-linear-gradient(top, #beebff 0%, #a8e4ff 100%);
|
||||
background: linear-gradient(to bottom, #beebff 0%, #a8e4ff 100%);
|
||||
/*filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='$color1', endColorstr='$color2',GradientType=0 );*/
|
||||
}
|
||||
.jstree-default .jstree-node {
|
||||
min-height: 24px;
|
||||
line-height: 24px;
|
||||
margin-left: 24px;
|
||||
min-width: 24px;
|
||||
}
|
||||
.jstree-default .jstree-anchor {
|
||||
line-height: 24px;
|
||||
height: 24px;
|
||||
}
|
||||
.jstree-default .jstree-icon {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
line-height: 24px;
|
||||
}
|
||||
.jstree-default .jstree-icon:empty {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
line-height: 24px;
|
||||
}
|
||||
.jstree-default.jstree-rtl .jstree-node {
|
||||
margin-right: 24px;
|
||||
}
|
||||
.jstree-default .jstree-wholerow {
|
||||
height: 24px;
|
||||
}
|
||||
.jstree-default .jstree-node,
|
||||
.jstree-default .jstree-icon {
|
||||
background-image: url("../../assets/images/jstree/32px.png");
|
||||
}
|
||||
.jstree-default .jstree-node {
|
||||
background-position: -292px -4px;
|
||||
background-repeat: repeat-y;
|
||||
}
|
||||
.jstree-default .jstree-last {
|
||||
background: transparent;
|
||||
}
|
||||
.jstree-default .jstree-open > .jstree-ocl {
|
||||
background-position: -132px -4px;
|
||||
}
|
||||
.jstree-default .jstree-closed > .jstree-ocl {
|
||||
background-position: -100px -4px;
|
||||
}
|
||||
.jstree-default .jstree-leaf > .jstree-ocl {
|
||||
background-position: -68px -4px;
|
||||
}
|
||||
.jstree-default .jstree-themeicon {
|
||||
background-position: -260px -4px;
|
||||
}
|
||||
.jstree-default > .jstree-no-dots .jstree-node,
|
||||
.jstree-default > .jstree-no-dots .jstree-leaf > .jstree-ocl {
|
||||
background: transparent;
|
||||
}
|
||||
.jstree-default > .jstree-no-dots .jstree-open > .jstree-ocl {
|
||||
background-position: -36px -4px;
|
||||
}
|
||||
.jstree-default > .jstree-no-dots .jstree-closed > .jstree-ocl {
|
||||
background-position: -4px -4px;
|
||||
}
|
||||
.jstree-default .jstree-disabled {
|
||||
background: transparent;
|
||||
}
|
||||
.jstree-default .jstree-disabled.jstree-hovered {
|
||||
background: transparent;
|
||||
}
|
||||
.jstree-default .jstree-disabled.jstree-clicked {
|
||||
background: #efefef;
|
||||
}
|
||||
.jstree-default .jstree-checkbox {
|
||||
background-position: -164px -4px;
|
||||
}
|
||||
.jstree-default .jstree-checkbox:hover {
|
||||
background-position: -164px -36px;
|
||||
}
|
||||
.jstree-default.jstree-checkbox-selection .jstree-clicked > .jstree-checkbox,
|
||||
.jstree-default .jstree-checked > .jstree-checkbox {
|
||||
background-position: -228px -4px;
|
||||
}
|
||||
.jstree-default.jstree-checkbox-selection .jstree-clicked > .jstree-checkbox:hover,
|
||||
.jstree-default .jstree-checked > .jstree-checkbox:hover {
|
||||
background-position: -228px -36px;
|
||||
}
|
||||
.jstree-default .jstree-anchor > .jstree-undetermined {
|
||||
background-position: -196px -4px;
|
||||
}
|
||||
.jstree-default .jstree-anchor > .jstree-undetermined:hover {
|
||||
background-position: -196px -36px;
|
||||
}
|
||||
.jstree-default > .jstree-striped {
|
||||
background-size: auto 48px;
|
||||
}
|
||||
.jstree-default.jstree-rtl .jstree-node {
|
||||
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAACAQMAAAB49I5GAAAABlBMVEUAAAAdHRvEkCwcAAAAAXRSTlMAQObYZgAAAAxJREFUCNdjAAMOBgAAGAAJMwQHdQAAAABJRU5ErkJggg==");
|
||||
background-position: 100% 1px;
|
||||
background-repeat: repeat-y;
|
||||
}
|
||||
.jstree-default.jstree-rtl .jstree-last {
|
||||
background: transparent;
|
||||
}
|
||||
.jstree-default.jstree-rtl .jstree-open > .jstree-ocl {
|
||||
background-position: -132px -36px;
|
||||
}
|
||||
.jstree-default.jstree-rtl .jstree-closed > .jstree-ocl {
|
||||
background-position: -100px -36px;
|
||||
}
|
||||
.jstree-default.jstree-rtl .jstree-leaf > .jstree-ocl {
|
||||
background-position: -68px -36px;
|
||||
}
|
||||
.jstree-default.jstree-rtl > .jstree-no-dots .jstree-node,
|
||||
.jstree-default.jstree-rtl > .jstree-no-dots .jstree-leaf > .jstree-ocl {
|
||||
background: transparent;
|
||||
}
|
||||
.jstree-default.jstree-rtl > .jstree-no-dots .jstree-open > .jstree-ocl {
|
||||
background-position: -36px -36px;
|
||||
}
|
||||
.jstree-default.jstree-rtl > .jstree-no-dots .jstree-closed > .jstree-ocl {
|
||||
background-position: -4px -36px;
|
||||
}
|
||||
.jstree-default .jstree-themeicon-custom {
|
||||
background-color: transparent;
|
||||
background-image: none;
|
||||
background-position: 0 0;
|
||||
}
|
||||
.jstree-default > .jstree-container-ul .jstree-loading > .jstree-ocl {
|
||||
background: url("../../assets/images/jstree/throbber.gif") center center no-repeat;
|
||||
}
|
||||
.jstree-default .jstree-file {
|
||||
background: url("../../assets/images/jstree/32px.png") -100px -68px no-repeat;
|
||||
}
|
||||
.jstree-default .jstree-folder {
|
||||
background: url("../../assets/images/jstree/32px.png") -260px -4px no-repeat;
|
||||
}
|
||||
.jstree-default.jstree-rtl .jstree-node {
|
||||
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAACAQMAAAB49I5GAAAABlBMVEUAAAAdHRvEkCwcAAAAAXRSTlMAQObYZgAAAAxJREFUCNdjAAMOBgAAGAAJMwQHdQAAAABJRU5ErkJggg==");
|
||||
}
|
||||
.jstree-default.jstree-rtl .jstree-last {
|
||||
background: transparent;
|
||||
}
|
||||
.jstree-default-small .jstree-node {
|
||||
min-height: 18px;
|
||||
line-height: 18px;
|
||||
margin-left: 18px;
|
||||
min-width: 18px;
|
||||
}
|
||||
.jstree-default-small .jstree-anchor {
|
||||
line-height: 18px;
|
||||
height: 18px;
|
||||
}
|
||||
.jstree-default-small .jstree-icon {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
line-height: 18px;
|
||||
}
|
||||
.jstree-default-small .jstree-icon:empty {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
line-height: 18px;
|
||||
}
|
||||
.jstree-default-small.jstree-rtl .jstree-node {
|
||||
margin-right: 18px;
|
||||
}
|
||||
.jstree-default-small .jstree-wholerow {
|
||||
height: 18px;
|
||||
}
|
||||
.jstree-default-small .jstree-node,
|
||||
.jstree-default-small .jstree-icon {
|
||||
background-image: url("../../assets/images/jstree/32px.png");
|
||||
}
|
||||
.jstree-default-small .jstree-node {
|
||||
background-position: -295px -7px;
|
||||
background-repeat: repeat-y;
|
||||
}
|
||||
.jstree-default-small .jstree-last {
|
||||
background: transparent;
|
||||
}
|
||||
.jstree-default-small .jstree-open > .jstree-ocl {
|
||||
background-position: -135px -7px;
|
||||
}
|
||||
.jstree-default-small .jstree-closed > .jstree-ocl {
|
||||
background-position: -103px -7px;
|
||||
}
|
||||
.jstree-default-small .jstree-leaf > .jstree-ocl {
|
||||
background-position: -71px -7px;
|
||||
}
|
||||
.jstree-default-small .jstree-themeicon {
|
||||
background-position: -263px -7px;
|
||||
}
|
||||
.jstree-default-small > .jstree-no-dots .jstree-node,
|
||||
.jstree-default-small > .jstree-no-dots .jstree-leaf > .jstree-ocl {
|
||||
background: transparent;
|
||||
}
|
||||
.jstree-default-small > .jstree-no-dots .jstree-open > .jstree-ocl {
|
||||
background-position: -39px -7px;
|
||||
}
|
||||
.jstree-default-small > .jstree-no-dots .jstree-closed > .jstree-ocl {
|
||||
background-position: -7px -7px;
|
||||
}
|
||||
.jstree-default-small .jstree-disabled {
|
||||
background: transparent;
|
||||
}
|
||||
.jstree-default-small .jstree-disabled.jstree-hovered {
|
||||
background: transparent;
|
||||
}
|
||||
.jstree-default-small .jstree-disabled.jstree-clicked {
|
||||
background: #efefef;
|
||||
}
|
||||
.jstree-default-small .jstree-checkbox {
|
||||
background-position: -167px -7px;
|
||||
}
|
||||
.jstree-default-small .jstree-checkbox:hover {
|
||||
background-position: -167px -39px;
|
||||
}
|
||||
.jstree-default-small.jstree-checkbox-selection .jstree-clicked > .jstree-checkbox,
|
||||
.jstree-default-small .jstree-checked > .jstree-checkbox {
|
||||
background-position: -231px -7px;
|
||||
}
|
||||
.jstree-default-small.jstree-checkbox-selection .jstree-clicked > .jstree-checkbox:hover,
|
||||
.jstree-default-small .jstree-checked > .jstree-checkbox:hover {
|
||||
background-position: -231px -39px;
|
||||
}
|
||||
.jstree-default-small .jstree-anchor > .jstree-undetermined {
|
||||
background-position: -199px -7px;
|
||||
}
|
||||
.jstree-default-small .jstree-anchor > .jstree-undetermined:hover {
|
||||
background-position: -199px -39px;
|
||||
}
|
||||
.jstree-default-small > .jstree-striped {
|
||||
background-size: auto 36px;
|
||||
}
|
||||
.jstree-default-small.jstree-rtl .jstree-node {
|
||||
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAACAQMAAAB49I5GAAAABlBMVEUAAAAdHRvEkCwcAAAAAXRSTlMAQObYZgAAAAxJREFUCNdjAAMOBgAAGAAJMwQHdQAAAABJRU5ErkJggg==");
|
||||
background-position: 100% 1px;
|
||||
background-repeat: repeat-y;
|
||||
}
|
||||
.jstree-default-small.jstree-rtl .jstree-last {
|
||||
background: transparent;
|
||||
}
|
||||
.jstree-default-small.jstree-rtl .jstree-open > .jstree-ocl {
|
||||
background-position: -135px -39px;
|
||||
}
|
||||
.jstree-default-small.jstree-rtl .jstree-closed > .jstree-ocl {
|
||||
background-position: -103px -39px;
|
||||
}
|
||||
.jstree-default-small.jstree-rtl .jstree-leaf > .jstree-ocl {
|
||||
background-position: -71px -39px;
|
||||
}
|
||||
.jstree-default-small.jstree-rtl > .jstree-no-dots .jstree-node,
|
||||
.jstree-default-small.jstree-rtl > .jstree-no-dots .jstree-leaf > .jstree-ocl {
|
||||
background: transparent;
|
||||
}
|
||||
.jstree-default-small.jstree-rtl > .jstree-no-dots .jstree-open > .jstree-ocl {
|
||||
background-position: -39px -39px;
|
||||
}
|
||||
.jstree-default-small.jstree-rtl > .jstree-no-dots .jstree-closed > .jstree-ocl {
|
||||
background-position: -7px -39px;
|
||||
}
|
||||
.jstree-default-small .jstree-themeicon-custom {
|
||||
background-color: transparent;
|
||||
background-image: none;
|
||||
background-position: 0 0;
|
||||
}
|
||||
.jstree-default-small > .jstree-container-ul .jstree-loading > .jstree-ocl {
|
||||
background: url("../../assets/images/jstree/throbber.gif") center center no-repeat;
|
||||
}
|
||||
.jstree-default-small .jstree-file {
|
||||
background: url("../../assets/images/jstree/32px.png") -103px -71px no-repeat;
|
||||
}
|
||||
.jstree-default-small .jstree-folder {
|
||||
background: url("../../assets/images/jstree/32px.png") -263px -7px no-repeat;
|
||||
}
|
||||
.jstree-default-small.jstree-rtl .jstree-node {
|
||||
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAACAQMAAABv1h6PAAAABlBMVEUAAAAdHRvEkCwcAAAAAXRSTlMAQObYZgAAAAxJREFUCNdjAAMHBgAAiABBI4gz9AAAAABJRU5ErkJggg==");
|
||||
}
|
||||
.jstree-default-small.jstree-rtl .jstree-last {
|
||||
background: transparent;
|
||||
}
|
||||
.jstree-default-large .jstree-node {
|
||||
min-height: 32px;
|
||||
line-height: 32px;
|
||||
margin-left: 32px;
|
||||
min-width: 32px;
|
||||
}
|
||||
.jstree-default-large .jstree-anchor {
|
||||
line-height: 32px;
|
||||
height: 32px;
|
||||
}
|
||||
.jstree-default-large .jstree-icon {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
line-height: 32px;
|
||||
}
|
||||
.jstree-default-large .jstree-icon:empty {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
line-height: 32px;
|
||||
}
|
||||
.jstree-default-large.jstree-rtl .jstree-node {
|
||||
margin-right: 32px;
|
||||
}
|
||||
.jstree-default-large .jstree-wholerow {
|
||||
height: 32px;
|
||||
}
|
||||
.jstree-default-large .jstree-node,
|
||||
.jstree-default-large .jstree-icon {
|
||||
background-image: url("../../assets/images/jstree/32px.png");
|
||||
}
|
||||
.jstree-default-large .jstree-node {
|
||||
background-position: -288px 0px;
|
||||
background-repeat: repeat-y;
|
||||
}
|
||||
.jstree-default-large .jstree-last {
|
||||
background: transparent;
|
||||
}
|
||||
.jstree-default-large .jstree-open > .jstree-ocl {
|
||||
background-position: -128px 0px;
|
||||
}
|
||||
.jstree-default-large .jstree-closed > .jstree-ocl {
|
||||
background-position: -96px 0px;
|
||||
}
|
||||
.jstree-default-large .jstree-leaf > .jstree-ocl {
|
||||
background-position: -64px 0px;
|
||||
}
|
||||
.jstree-default-large .jstree-themeicon {
|
||||
background-position: -256px 0px;
|
||||
}
|
||||
.jstree-default-large > .jstree-no-dots .jstree-node,
|
||||
.jstree-default-large > .jstree-no-dots .jstree-leaf > .jstree-ocl {
|
||||
background: transparent;
|
||||
}
|
||||
.jstree-default-large > .jstree-no-dots .jstree-open > .jstree-ocl {
|
||||
background-position: -32px 0px;
|
||||
}
|
||||
.jstree-default-large > .jstree-no-dots .jstree-closed > .jstree-ocl {
|
||||
background-position: 0px 0px;
|
||||
}
|
||||
.jstree-default-large .jstree-disabled {
|
||||
background: transparent;
|
||||
}
|
||||
.jstree-default-large .jstree-disabled.jstree-hovered {
|
||||
background: transparent;
|
||||
}
|
||||
.jstree-default-large .jstree-disabled.jstree-clicked {
|
||||
background: #efefef;
|
||||
}
|
||||
.jstree-default-large .jstree-checkbox {
|
||||
background-position: -160px 0px;
|
||||
}
|
||||
.jstree-default-large .jstree-checkbox:hover {
|
||||
background-position: -160px -32px;
|
||||
}
|
||||
.jstree-default-large.jstree-checkbox-selection .jstree-clicked > .jstree-checkbox,
|
||||
.jstree-default-large .jstree-checked > .jstree-checkbox {
|
||||
background-position: -224px 0px;
|
||||
}
|
||||
.jstree-default-large.jstree-checkbox-selection .jstree-clicked > .jstree-checkbox:hover,
|
||||
.jstree-default-large .jstree-checked > .jstree-checkbox:hover {
|
||||
background-position: -224px -32px;
|
||||
}
|
||||
.jstree-default-large .jstree-anchor > .jstree-undetermined {
|
||||
background-position: -192px 0px;
|
||||
}
|
||||
.jstree-default-large .jstree-anchor > .jstree-undetermined:hover {
|
||||
background-position: -192px -32px;
|
||||
}
|
||||
.jstree-default-large > .jstree-striped {
|
||||
background-size: auto 64px;
|
||||
}
|
||||
.jstree-default-large.jstree-rtl .jstree-node {
|
||||
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAACAQMAAAB49I5GAAAABlBMVEUAAAAdHRvEkCwcAAAAAXRSTlMAQObYZgAAAAxJREFUCNdjAAMOBgAAGAAJMwQHdQAAAABJRU5ErkJggg==");
|
||||
background-position: 100% 1px;
|
||||
background-repeat: repeat-y;
|
||||
}
|
||||
.jstree-default-large.jstree-rtl .jstree-last {
|
||||
background: transparent;
|
||||
}
|
||||
.jstree-default-large.jstree-rtl .jstree-open > .jstree-ocl {
|
||||
background-position: -128px -32px;
|
||||
}
|
||||
.jstree-default-large.jstree-rtl .jstree-closed > .jstree-ocl {
|
||||
background-position: -96px -32px;
|
||||
}
|
||||
.jstree-default-large.jstree-rtl .jstree-leaf > .jstree-ocl {
|
||||
background-position: -64px -32px;
|
||||
}
|
||||
.jstree-default-large.jstree-rtl > .jstree-no-dots .jstree-node,
|
||||
.jstree-default-large.jstree-rtl > .jstree-no-dots .jstree-leaf > .jstree-ocl {
|
||||
background: transparent;
|
||||
}
|
||||
.jstree-default-large.jstree-rtl > .jstree-no-dots .jstree-open > .jstree-ocl {
|
||||
background-position: -32px -32px;
|
||||
}
|
||||
.jstree-default-large.jstree-rtl > .jstree-no-dots .jstree-closed > .jstree-ocl {
|
||||
background-position: 0px -32px;
|
||||
}
|
||||
.jstree-default-large .jstree-themeicon-custom {
|
||||
background-color: transparent;
|
||||
background-image: none;
|
||||
background-position: 0 0;
|
||||
}
|
||||
.jstree-default-large > .jstree-container-ul .jstree-loading > .jstree-ocl {
|
||||
background: url("../../assets/images/jstree/throbber.gif") center center no-repeat;
|
||||
}
|
||||
.jstree-default-large .jstree-file {
|
||||
background: url("../../assets/images/jstree/32px.png") -96px -64px no-repeat;
|
||||
}
|
||||
.jstree-default-large .jstree-folder {
|
||||
background: url("../../assets/images/jstree/32px.png") -256px 0px no-repeat;
|
||||
}
|
||||
.jstree-default-large.jstree-rtl .jstree-node {
|
||||
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAACAQMAAAAD0EyKAAAABlBMVEUAAAAdHRvEkCwcAAAAAXRSTlMAQObYZgAAAAxJREFUCNdjgIIGBgABCgCBvVLXcAAAAABJRU5ErkJggg==");
|
||||
}
|
||||
.jstree-default-large.jstree-rtl .jstree-last {
|
||||
background: transparent;
|
||||
}
|
||||
@media (max-width: 768px) {
|
||||
#jstree-dnd.jstree-dnd-responsive {
|
||||
line-height: 40px;
|
||||
font-weight: bold;
|
||||
font-size: 1.1em;
|
||||
text-shadow: 1px 1px white;
|
||||
}
|
||||
#jstree-dnd.jstree-dnd-responsive > i {
|
||||
background: transparent;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
#jstree-dnd.jstree-dnd-responsive > .jstree-ok {
|
||||
background-image: url("../../assets/images/jstree/40px.png");
|
||||
background-position: 0 -200px;
|
||||
background-size: 120px 240px;
|
||||
}
|
||||
#jstree-dnd.jstree-dnd-responsive > .jstree-er {
|
||||
background-image: url("../../assets/images/jstree/40px.png");
|
||||
background-position: -40px -200px;
|
||||
background-size: 120px 240px;
|
||||
}
|
||||
#jstree-marker.jstree-dnd-responsive {
|
||||
border-left-width: 10px;
|
||||
border-top-width: 10px;
|
||||
border-bottom-width: 10px;
|
||||
margin-top: -10px;
|
||||
}
|
||||
}
|
||||
@media (max-width: 768px) {
|
||||
.jstree-default-responsive {
|
||||
/*
|
||||
.jstree-open > .jstree-ocl,
|
||||
.jstree-closed > .jstree-ocl { border-radius:20px; background-color:white; }
|
||||
*/
|
||||
}
|
||||
.jstree-default-responsive .jstree-icon {
|
||||
background-image: url("../../assets/images/jstree/40px.png");
|
||||
}
|
||||
.jstree-default-responsive .jstree-node,
|
||||
.jstree-default-responsive .jstree-leaf > .jstree-ocl {
|
||||
background: transparent;
|
||||
}
|
||||
.jstree-default-responsive .jstree-node {
|
||||
min-height: 40px;
|
||||
line-height: 40px;
|
||||
margin-left: 40px;
|
||||
min-width: 40px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.jstree-default-responsive .jstree-anchor {
|
||||
line-height: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
.jstree-default-responsive .jstree-icon,
|
||||
.jstree-default-responsive .jstree-icon:empty {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
}
|
||||
.jstree-default-responsive > .jstree-container-ul > .jstree-node {
|
||||
margin-left: 0;
|
||||
}
|
||||
.jstree-default-responsive.jstree-rtl .jstree-node {
|
||||
margin-left: 0;
|
||||
margin-right: 40px;
|
||||
}
|
||||
.jstree-default-responsive.jstree-rtl .jstree-container-ul > .jstree-node {
|
||||
margin-right: 0;
|
||||
}
|
||||
.jstree-default-responsive .jstree-ocl,
|
||||
.jstree-default-responsive .jstree-themeicon,
|
||||
.jstree-default-responsive .jstree-checkbox {
|
||||
background-size: 120px 240px;
|
||||
}
|
||||
.jstree-default-responsive .jstree-leaf > .jstree-ocl {
|
||||
background: transparent;
|
||||
}
|
||||
.jstree-default-responsive .jstree-open > .jstree-ocl {
|
||||
background-position: 0 0px !important;
|
||||
}
|
||||
.jstree-default-responsive .jstree-closed > .jstree-ocl {
|
||||
background-position: 0 -40px !important;
|
||||
}
|
||||
.jstree-default-responsive.jstree-rtl .jstree-closed > .jstree-ocl {
|
||||
background-position: -40px 0px !important;
|
||||
}
|
||||
.jstree-default-responsive .jstree-themeicon {
|
||||
background-position: -40px -40px;
|
||||
}
|
||||
.jstree-default-responsive .jstree-checkbox,
|
||||
.jstree-default-responsive .jstree-checkbox:hover {
|
||||
background-position: -40px -80px;
|
||||
}
|
||||
.jstree-default-responsive.jstree-checkbox-selection .jstree-clicked > .jstree-checkbox,
|
||||
.jstree-default-responsive.jstree-checkbox-selection .jstree-clicked > .jstree-checkbox:hover,
|
||||
.jstree-default-responsive .jstree-checked > .jstree-checkbox,
|
||||
.jstree-default-responsive .jstree-checked > .jstree-checkbox:hover {
|
||||
background-position: 0 -80px;
|
||||
}
|
||||
.jstree-default-responsive .jstree-anchor > .jstree-undetermined,
|
||||
.jstree-default-responsive .jstree-anchor > .jstree-undetermined:hover {
|
||||
background-position: 0 -120px;
|
||||
}
|
||||
.jstree-default-responsive .jstree-anchor {
|
||||
font-weight: bold;
|
||||
font-size: 1.1em;
|
||||
text-shadow: 1px 1px white;
|
||||
}
|
||||
.jstree-default-responsive > .jstree-striped {
|
||||
background: transparent;
|
||||
}
|
||||
.jstree-default-responsive .jstree-wholerow {
|
||||
border-top: 1px solid rgba(255, 255, 255, 0.7);
|
||||
border-bottom: 1px solid rgba(64, 64, 64, 0.2);
|
||||
background: #ebebeb;
|
||||
height: 40px;
|
||||
}
|
||||
.jstree-default-responsive .jstree-wholerow-hovered {
|
||||
background: #e7f4f9;
|
||||
}
|
||||
.jstree-default-responsive .jstree-wholerow-clicked {
|
||||
background: #beebff;
|
||||
}
|
||||
.jstree-default-responsive .jstree-children .jstree-last > .jstree-wholerow {
|
||||
box-shadow: inset 0 -6px 3px -5px #666666;
|
||||
}
|
||||
.jstree-default-responsive .jstree-children .jstree-open > .jstree-wholerow {
|
||||
box-shadow: inset 0 6px 3px -5px #666666;
|
||||
border-top: 0;
|
||||
}
|
||||
.jstree-default-responsive .jstree-children .jstree-open + .jstree-open {
|
||||
box-shadow: none;
|
||||
}
|
||||
.jstree-default-responsive .jstree-node,
|
||||
.jstree-default-responsive .jstree-icon,
|
||||
.jstree-default-responsive .jstree-node > .jstree-ocl,
|
||||
.jstree-default-responsive .jstree-themeicon,
|
||||
.jstree-default-responsive .jstree-checkbox {
|
||||
background-image: url("../../assets/images/jstree/40px.png");
|
||||
background-size: 120px 240px;
|
||||
}
|
||||
.jstree-default-responsive .jstree-node {
|
||||
background-position: -80px 0;
|
||||
background-repeat: repeat-y;
|
||||
}
|
||||
.jstree-default-responsive .jstree-last {
|
||||
background: transparent;
|
||||
}
|
||||
.jstree-default-responsive .jstree-leaf > .jstree-ocl {
|
||||
background-position: -40px -120px;
|
||||
}
|
||||
.jstree-default-responsive .jstree-last > .jstree-ocl {
|
||||
background-position: -40px -160px;
|
||||
}
|
||||
.jstree-default-responsive .jstree-themeicon-custom {
|
||||
background-color: transparent;
|
||||
background-image: none;
|
||||
background-position: 0 0;
|
||||
}
|
||||
.jstree-default-responsive .jstree-file {
|
||||
background: url("../../assets/images/jstree/40px.png") 0 -160px no-repeat;
|
||||
background-size: 120px 240px;
|
||||
}
|
||||
.jstree-default-responsive .jstree-folder {
|
||||
background: url("../../assets/images/jstree/40px.png") -40px -40px no-repeat;
|
||||
background-size: 120px 240px;
|
||||
}
|
||||
}
|
||||
.jstree-default > .jstree-container-ul > .jstree-node {
|
||||
margin-left: 0;
|
||||
margin-right: 0;
|
||||
}
|
||||
@@ -1032,7 +1032,7 @@ libraries:
|
||||
add_to_history_collection: '.add-to-history-collection'
|
||||
# TODO: Most of these aren't very good selectors but the same DOM elements
|
||||
# are reused without adding specific classes, IDs, or roles to anything.
|
||||
import_modal: '.modal'
|
||||
import_modal: '.directory-dataset-picker'
|
||||
import_datasets_from_history_modal: '.selection-dialog-modal'
|
||||
import_datasets_from_history_modal_history_search: '.selection-dialog-modal .search-query'
|
||||
import_datasets_from_history_modal_dataset_search: '.selection-dialog-modal input[placeholder="search datasets"]'
|
||||
@@ -1041,8 +1041,15 @@ libraries:
|
||||
import_datasets_from_history_modal_select_list_item_by_index: '.selection-dialog-modal table tbody tr[aria-rowindex="${row_index}"] td[aria-colindex="1"]'
|
||||
import_datasets_from_history_modal_ok: '.selection-dialog-modal [data-description="selection dialog ok"]'
|
||||
import_datasets_from_history_modal_cancel: '.selection-dialog-modal [data-description="selection dialog cancel"]'
|
||||
import_datasets_ok_button: '.modal-footer .buttons #button-0'
|
||||
import_datasets_cancel_button: '.modal-footer .buttons #button-1'
|
||||
add_to_history_as_collection:
|
||||
type: xpath
|
||||
selector: '//button[contains(text(), "Continue")]'
|
||||
import_datasets_ok_button:
|
||||
type: xpath
|
||||
selector: '//button[contains(text(), "Import")]'
|
||||
import_datasets_cancel_button:
|
||||
type: xpath
|
||||
selector: '//button[contains(text(), "Close")]'
|
||||
export_to_history_options: '#library-collection-type-select'
|
||||
export_to_history_paired_option: 'option[value="${collection_option}"]'
|
||||
export_to_history_collection_name: '.collection-name'
|
||||
@@ -1066,8 +1073,10 @@ libraries:
|
||||
download_button: '#download-btn'
|
||||
delete_btn: '.toolbtn-bulk-delete'
|
||||
toast_msg: '.b-toast'
|
||||
toast_warning: '.b-toast-warning'
|
||||
select_import_dir_item: 'li[full_path="${name}"] .jstree-anchor'
|
||||
alert_not_exists_user_import_dir:
|
||||
type: xpath
|
||||
selector: //div[contains(@class, "alert-danger") and contains(normalize-space(text()), "Your user import directory does not exist")]
|
||||
select_import_dir_item: '[for="drilldown-option-${name}"]'
|
||||
import_dir_btn:
|
||||
type: xpath
|
||||
selector: '//button[contains(text(), "Import")]'
|
||||
|
||||
@@ -63,7 +63,7 @@ class TestLibraryToCollections(SeleniumTestCase, UsesLibraryAssertions):
|
||||
collection_option=collection_option
|
||||
).wait_for_and_click()
|
||||
self.screenshot(f"libraries_to_collection_landing_is_new_history={is_new_history}")
|
||||
self.components.libraries.folder.import_datasets_ok_button.wait_for_and_click()
|
||||
self.components.libraries.folder.add_to_history_as_collection.wait_for_and_click()
|
||||
self.build_collection_and_assert()
|
||||
if is_new_history:
|
||||
assert self.history_panel_name_element().text == random_name
|
||||
@@ -78,7 +78,7 @@ class TestLibraryToCollections(SeleniumTestCase, UsesLibraryAssertions):
|
||||
collection_option="list:paired"
|
||||
).wait_for_and_click()
|
||||
self.screenshot(f"test_export_pairs_list={is_new_history}")
|
||||
self.components.libraries.folder.import_datasets_ok_button.wait_for_and_click()
|
||||
self.components.libraries.folder.add_to_history_as_collection.wait_for_and_click()
|
||||
self.components.libraries.folder.clear_filters.wait_for_and_click()
|
||||
self.collection_builder_click_paired_item("forward", 0)
|
||||
self.collection_builder_click_paired_item("reverse", 1)
|
||||
|
||||
@@ -57,7 +57,7 @@ class TestUserLibraryImport(SeleniumIntegrationTestCase):
|
||||
self.wait_for_selector_absent_or_hidden(self.modal_body_selector())
|
||||
|
||||
# assert 'user import folder was not created' warning
|
||||
self.components.libraries.folder.toast_warning.wait_for_visible()
|
||||
self.components.libraries.folder.alert_not_exists_user_import_dir.wait_for_visible()
|
||||
|
||||
@selenium_test
|
||||
def test_user_library_dataset_permissions(self):
|
||||
|
||||
Reference in New Issue
Block a user